# Yape-Recurring Integration Guide

> Yape is a new alternative payment method for Peru that allows the customer authorizes the merchant to make charges using Yape without the need to approve future payments.

# Yape Recurring

Yape Recurring, or Yape-On-File, is secure and built for the mobile-first Peruvian market.
A credential-on-file solution that lets users store and link their Yape account directly at checkout. No more QR scans or OTPs needed after the first authorization.

Yape allows merchants to set up and manage recurring payments through the EBANX API. The customer authorizes the merchant to make charges using Yape without the need to approve future payments. This solution can be used for recurring payments (subscription/enrollment) or one-click payments (using the previously performed enrollment to process transactions without extra user interaction), reducing barriers for customers and making the subscription process more accessible and streamlined. It also creates an opportunity for global companies to establish themselves in Peru.

## Requirements

- **API authentication** - All API requests must be authenticated using [JWS (JSON Web Signature)](/docs/get-started/api-authentication/jws-authentication). The legacy `integration_key` is being deprecated — if you still use it, follow the [Migration Guide](/docs/get-started/api-authentication/jws-migration) to transition to JWS. If you don't have credentials yet, complete the [Merchant Signup Form](https://www.ebanx.com/en/contact/).

## How it works

- **1. Enrollment** - Customers authorize recurring payments through an **app-to-app** or **web-to-app** flow. The enrollment process has two different user experiences depending on where the customer is coming from:
  - **App-to-App (mobile)**: Considering a mobile app experience, the merchant can request the enrollment and receive a deeplink URL to redirect the customer to Yape's app, where he/she can confirm the enrollment.
  - **Web-to-App Flow (web)**: On a web browser user experience, the merchant requests the enrollment and the customer will have to open their Yape app and approve the enrollment. Once approved, the merchant will receive a notification informing a change in status of the enrollment. The merchant can query the merchant enrollment code to get the latest status anytime.
- **2. Enrollment Status update** - EBANX notifies merchants of enrollment status updates via webhooks to the registered URL.
- **3. Subsequent payments** - Once enrolled, future payments occur automatically using the `merchant_enrollment_code`, without requiring additional customer action.
- **4. Enrollment payment update** - EBANX notifies merchants of payment status updates via webhooks to the registered URL.

## Instructions

Follow the steps below.

### Select your environment
Select the appropriate environment for your integration. Use the sandbox environment for testing, or the production environment for live transactions. Use the URL for your HTTP requests based on your selection.

- **Cross-border sandbox:** `https://sandbox.ebanxpay.com/ws/userenrollment`
- **Cross-border production:** `https://api.ebanxpay.com/ws/userenrollment`
- **Local sandbox:** `https://sandbox-local-latam.ebanxpay.com/ws/userenrollment`
- **Local production:** `https://api-local-latam.ebanxpay.com/ws/userenrollment`

Check the method's availability for your country and tenant in [Payment Methods by Country](/docs/pay-in/processing/payment-methods/payment-methods-overview#payment-methods-by-country). Questions about tenant and environment? Check our [API Operability](/docs/get-started/api-operability) and [API Endpoints](/docs/get-started/api-endpoints).

### Define your enrollment parameters

The enrollment is a necessary step where the customer reviews and approves their wallet to be accessed by the merchant, allowing the merchant to make charges to their account when necessary. The same customer can have multiple enrollments for the same merchant.

The `phone` is the key on the Yape side to identify the customer account.

#### Basic parameters

| Parameter               | Requirement | Description              |
| ----------------------- | ----------- | ------------------------ |
| **`integration_key`**   | Required    | Your integration key     |
| **`payment_type_code`** | Required    | Must be `yape-recurrent` |
| **`operation`**         | Required    | Must be `enrollment`     |

  

#### Enrollment Data

| Parameter                                  | Requirement | Description                                                                                                                              |
| ------------------------------------------ | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| **`enrollment.merchant_enrollment_code`**  | Required    | Unique identifier associated with the recurrence                                                                                         |
| **`enrollment.phone`**                     | Required    | Customer phone number connected to the Yape Account                                                                                      |
| **`enrollment.email`**                     | Required    | Customer email address                                                                                                                   |
| **`enrollment.country`**                   | Required    | Must be `PE`                                                                                                                             |
| **`enrollment.subscription.frequency`**    | Required    | The billing cycle of the enrollment. Available frequencies are: `monthly`,`bimonthly`, `quarterly`, `halfyearly`, `yearly` or `ondemand` |
| **`enrollment.subscription.fixed_amount`** | Optional    | Local amount definition provided when recurring payments will have a fixed value.                                                        |
| **`enrollment.subscription.source`**       | Required    | String `web` OR `mobile` depending on customer device                                                                  |

### Enrollment request

The enrollment step is essential for registering customers for automatic payments. This process is handled through the **`/ws/userenrollment`** endpoint and the `enrollment.subscription.source` field determines the user experience, dictating whether they have to manually open their Yape App on the phone (`web`) or are redirected via the `redirect_url` provided in the response (`mobile`).

    #### App-to-App Request
      ```bash
curl -X POST \
  --location 'https://sandbox.ebanxpay.com/ws/userenrollment' \
  --header 'Content-Type: application/json' \
  --data '{
    "integration_key": "{{integration_key}}",
    "operation": "enrollment",
    "payment_type_code": "yape-recurrent",
    "enrollment": {
        "merchant_enrollment_code": "{{unique_enrollment_code}}",
        "phone_number": "5555555555",
        "email": "john.doe@example.com",
        "country": "pe",
        "subscription": {
            "frequency": "{{frequency}}",
            "fixed_amount": "99.85",
            "source": "mobile"
        }
    }
}'
```
    </TabItem>
    #### Web-to-App Request
      ```bash
curl -X POST \
  --location 'https://sandbox.ebanxpay.com/ws/userenrollment' \
  --header 'Content-Type: application/json' \
  --data '{
    "integration_key": "{{integration_key}}",
    "operation": "enrollment",
    "payment_type_code": "yape-recurrent",
    "enrollment": {
        "merchant_enrollment_code": "{{unique_enrollment_code}}",
        "phone_number": "5555555555",
        "email": "john.doe@example.com",
        "country": "pe",
        "subscription": {
            "frequency": "{{frequency}}",
            "fixed_amount": "99.85",
            "source": "web"
        }
    }
}'
```

### Enrollment response

The response to this call will indicate the status of the operation, returning SUCCESS and your enrollment definitions.

- App-to-App flow (`mobile`): The response will contain a redirect_url to send your customer directly to the Yape App.
- Web-to-App flow (`web`): A redirect_url will also be provided, linking to an EBANX instructions page. This is optional; if you already render your own Yape instructions, you may ignore this field.

    #### App-to-App Response
      ```json
{
  "status": "SUCCESS",
  "redirect_url": "{{redirect_url}}",
  "enrollment": {
    "merchant_enrollment_code": "{{unique_enrollment_code}}",
    "country": "pe",
    "email": "john.doe@example.com",
    "phone_number": "5555555555",
    "subscription": {
      "frequency": "{{frequency}}",
      "fixed_amount": "99.85",
      "source": "mobile"
    }
  }
}
```
    </TabItem>
    #### Web-to-App Response
      ```json
{
  "status": "SUCCESS",
  "redirect_url": "{{redirect_url}}",
  "enrollment": {
    "merchant_enrollment_code": "{{unique_enrollment_code}}",
    "country": "pe",
    "email": "john.doe@example.com",
    "phone_number": "5555555555",
    "subscription": {
      "frequency": "{{frequency}}",
      "fixed_amount": "99.85",
      "source": "web"
    }
  }
}
```

**Sandbox Behavior** - When working in a sandbox environment, the `redirect_url` will lead to a sandbox interface where you can simulate customer acceptance or cancellation of the enrollment agreement.

See example below.

![Yape recurring sandbox enrollment agreement interface with accept and cancel options](/img/docs/pay-in/processing/payment-methods/country-specific/peru/sandbox-recurrency-agreement.png)

### Enrollment status check

Users purchasing for the first time need to be enrolled and authorized the payment. To check if the customer has accepted the recurrency and the latest status of the enrollment, the merchant can query the merchant_enrollment_code, sending a request to the `/ws/userenrollments/query` endpoint.

Use the following parameters when preparing your request.

| Parameter                      | Requirement | Description                                                                               |
| ------------------------------ | ----------- | ----------------------------------------------------------------------------------------- |
| **`integration_key`**          | Required    | Your EBANX integration key from Merchant Area                                           |
| **`operation`**                | Required    | Set to `enrollment`                                                                       |
| **`payment_type_code`**        | Required    | Set to `yape-recurrent`                                                                   |
| **`merchant_enrollment_code`** | Required    | Unique identifier defined by the merchant to be associated with that specific enrollment. |
| **`country`**                  | Required    | Must be `pe`                                                                              |

  

Sample request:

```bash
curl -X POST \
  --location 'https://sandbox.ebanxpay.com/ws/userenrollments/query' \
  --header 'Content-Type: application/json' \
  --data '{
    "integration_key": "{{integration_key}}",
    "operation": "enrollment",
    "payment_type_code": "yape-recurrent",
    "enrollment": {
        "merchant_enrollment_code": "{{unique_enrollment_code}}",
        "country": "pe"
    }
}'
```

Sample response (success):

```json
{
  "status": "SUCCESS",
  "enrollment": {
    "status": "accepted"
  }
}
```

A successful request will return a JSON response like the one above, with a status of `accepted` for the enrollment approved by the customer. Other possible enrollment statuses include `not_accepted`, `pending`, `expired`, `revoked`, and `cancelled`, depending on the actions taken by the merchant or customer.

### Cancel an existing enrollment

Customers can request the enrollment cancellation at any time. To abide by the customer's request, the merchant must call a cancel endpoint to revoke the enrollment. Once an enrollment is revoked, it can no longer be used for future transactions. If the customer wishes to process new payments, a new enrollment must be requested.

Enrollments can be canceled by sending a POST request to the `/ws/userenrollment` endpoint with `operation` set to `cancel` and `payment_type_code` set to `yape-recurrent`.

Sample request:

```bash
curl -X POST \
  --location 'https://sandbox.ebanxpay.com/ws/userenrollment' \
  --header 'Content-Type: application/json' \
  --data '{
    "integration_key": "{{integration_key}}",
    "operation": "cancel",
    "payment_type_code": "yape-recurrent",
    "enrollment": {
        "merchant_enrollment_code": "{{unique_enrollment_code}}",
        "country": "pe"
    }
}'
```

Sample response (success):

```json
{
  "status": "SUCCESS",
  "enrollment": {
    "status": "revoked"
  }
}
```

### Payment request

Merchants can request payments whenever necessary as long as there is an active enrollment for that customer, calling the **ws/direct** endpoint with the required parameters.

|Parameter|Requirement|Description|
|--|--|--|
|**`integration_key`**|Required|Your EBANX integration key|
|**`name`**|Required|Customer full name|
|**`merchant_payment_code`**|Required|Unique merchant payment code|
|**`amount_total`**|Required|Total amount to be charged. Note that the amount must match the one set in the enrollment|
|**`currency_code`** |Required|Must be `PEN`|
|**`country`** |Required|Must be `pe`|
|**`payment_type_code`** |Required|Must be `yape-recurrent`|
|**`email`**|Required|Customer e-mail|
|**`phone_number`**|Required|Customer phone number that is the Yape account key|
|**`enrollment.merchant_enrollment_code`**|Required|The enrollment code generated in the previous steps. The enrollment must have a `accepted` status to be used in recurring payments|

  

Check the example:

```bash
curl -X POST \
  --location 'https://sandbox.ebanxpay.com/ws/direct' \
  --header 'Content-Type: application/json' \
  --data '{
    "integration_key": "{{integration_key}}",
    "payment": {
        "name": "John Doe",
        "email": "john.doe@example.com",
        "phone_number": "5555555555",
        "document": "{{tax_id}}",
        "country": "pe",
        "payment_type_code": "yape-recurrent",
        "merchant_payment_code": "{{unique_merchant_code}}",
        "currency_code": "PEN",
        "amount_total": 99.85,
        "enrollment": {
            "merchant_enrollment_code": "{{unique_enrollment_code}}"
        }
    }
}'
```

### Payment response

The response of this call will have a Pending (**PE**) status, and there will be no redirection.
There is not action from the customer during the payment flow, everything will run without customer interaction.

**Response:**

```json
{
  "status": "SUCCESS",
  "payment": {
    "hash": "59acc5f00945fa382ab051651440826da7701533249b3a475",
    "country": "pe",
    "merchant_payment_code": "{{unique_merchant_code}}",
    "status": "PE",
    "status_date": "{{YYYY-MM-DD HH:mm:ss}}",
    "open_date": "{{YYYY-MM-DD HH:mm:ss}}",
    "confirm_date": null,
    "amount_br": "99.85",
    "amount_ext": "99.85",
    "amount_iof": "0.00",
    "amount_ext_requested": "99.85",
    "currency_rate": "1.0000",
    "currency_ext": "PEN",
    "payment_type_code": "yape-recurrent",
    "order_number": null,
    "due_date": "2024-06-12",
    "instalments": "1",
    "transfer_date": null,
    "pre_approved": false,
    "capture_available": null,
    "requested_currency": "PEN",
    "transaction_status": {
      "acquirer": "EBANX",
      "code": "OK",
      "description": "Payment successfully paid",
      "description_code": "ACCEPTED"
    }
  }
}
```

### Monitor payment for status changes

**Notifications**

- Payments do not require customer interaction or manual authorization. Payment confirmation is asynchronous and may take a few seconds. Once the payment is confirmed, EBANX sends a webhook notification to the `notification_url` stored in your Merchant Area to inform that the status has changed for a specific transaction.

- Make sure your system is set up to receive notifications from EBANX for any changes in payment status.

- [Learn more about Payment Notifications](/docs/pay-in/management/status-and-retrieval/payment-notifications)

**Status**

- After receiving a notification that status has changed, retrieve the payment status.

- When a payment is confirmed, the status will change from **pending** (**PE**) to **confirmed** (**CO**).
  If the customer does not complete the payment, the status will eventually change to **canceled (CA)**.

- [Learn more about Retrieving Payment Status](/docs/pay-in/management/status-and-retrieval/retrieve-payment)

### Alternative: Enroll and charge in a single request

As an alternative to the two-step process described above (steps 2-8), you can create an enrollment and a payment in a single API request to the **/ws/direct** endpoint. This simplifies the integration by combining the enrollment creation and the first payment into one operation. The customer will still need to authorize the enrollment through the Yape app. Once authorized, the payment will be processed automatically.

#### Parameters

| **Parameter**                                        | **Description**                                     |          |
| ---------------------------------------------------- | --------------------------------------------------- | -------- |
| `integration_key`                                    | Your EBANX integration key.                         | Required |
| `payment.payment_type_code`                          | Set to `yape-recurrent`.                            | Required |
| `payment.merchant_payment_code`                      | Unique ID for the payment.                          | Required |
| `payment.email`                                      | Customer email.                                     | Required |
| `payment.country`                                    | Set to `pe`.                                        | Required |
| `payment.currency_code`                              | Set to `PEN`.                                       | Required |
| `payment.phone_number`                               | Customer phone number connected to the Yape account.| Required |
| `payment.amount_total`                               | Total amount to charge.                             | Required |
| `payment.enrollment.merchant_enrollment_code`        | Unique ID for the recurring enrollment.             | Required |
| `payment.enrollment.subscription.frequency`          | Billing cycle: `monthly`, `bimonthly`, `quarterly`, `halfyearly`, `yearly`, or `ondemand`. | Required |
| `payment.enrollment.subscription.source`             | `mobile` (app-to-app) or `web` (web-to-app).       | Required |

### Enroll and charge request

Send the combined enrollment and charge request to the **/ws/direct** endpoint. The `subscription.source` field determines the customer experience, just like in the standard enrollment flow.

    #### App-to-App (source: mobile)
      ```bash
curl -X POST \
  --location 'https://sandbox.ebanxpay.com/ws/direct' \
  --header 'Content-Type: application/json' \
  --data '{
    "integration_key": "{{integration_key}}",
    "payment": {
        "merchant_payment_code": "{{unique_merchant_code}}",
        "payment_type_code": "yape-recurrent",
        "amount_total": 99.85,
        "country": "pe",
        "currency_code": "PEN",
        "email": "john.doe@example.com",
        "phone_number": "5555555555",
        "enrollment": {
            "merchant_enrollment_code": "{{unique_enrollment_code}}",
            "subscription": {
                "frequency": "{{frequency}}",
                "source": "mobile"
            }
        }
    }
}'
```
    </TabItem>
    #### Web-to-App (source: web)
      ```bash
curl -X POST \
  --location 'https://sandbox.ebanxpay.com/ws/direct' \
  --header 'Content-Type: application/json' \
  --data '{
    "integration_key": "{{integration_key}}",
    "payment": {
        "merchant_payment_code": "{{unique_merchant_code}}",
        "payment_type_code": "yape-recurrent",
        "amount_total": 99.85,
        "country": "pe",
        "currency_code": "PEN",
        "email": "john.doe@example.com",
        "phone_number": "5555555555",
        "enrollment": {
            "merchant_enrollment_code": "{{unique_enrollment_code}}",
            "subscription": {
                "frequency": "{{frequency}}",
                "source": "web"
            }
        }
    }
}'
```

### Enroll and charge response

The response confirms that both the enrollment and the payment have been created.
The enrollment remains in a pending state until the customer authorizes it through the Yape app.

- App-to-App flow (`mobile`): The response will contain a redirect_url to send your customer directly to the Yape App.
- Web-to-App flow (`web`): A redirect_url will also be provided, linking to an EBANX instructions page. This is optional; if you already render your own Yape instructions, you may ignore this field.

    #### App-to-App Response (mobile)
      ```json
{
  "payment": {
    "hash": "59acc5f00945fa382ab051651440826da7701533249b3a475",
    "country": "pe",
    "merchant_payment_code": "{{unique_merchant_code}}",
    "order_number": null,
    "status": "PE",
    "status_date": "{{YYYY-MM-DD HH:mm:ss}}",
    "open_date": "{{YYYY-MM-DD HH:mm:ss}}",
    "confirm_date": null,
    "transfer_date": null,
    "amount_br": "99.85",
    "amount_ext": "99.85",
    "amount_iof": "1",
    "amount_ext_requested": "99.85",
    "currency_rate": "1",
    "currency_ext": "PEN",
    "due_date": "{{YYYY-MM-DD HH:mm:ss}}",
    "instalments": "1",
    "payment_type_code": "yape-recurrent",
    "pre_approved": false,
    "capture_available": null,
    "redirect_url": "{{redirect_url}}",
    "enrollment": {
      "status": "pending",
      "merchant_enrollment_code": "{{unique_enrollment_code}}"
    }
  },
  "status": "SUCCESS",
  "redirect_url": "{{redirect_url}}"
}
```
    </TabItem>
    #### Web-to-App Response (web)
      ```json
{
  "payment": {
    "hash": "59acc5f00945fa382ab051651440826da7701533249b3a475",
    "country": "pe",
    "merchant_payment_code": "{{unique_merchant_code}}",
    "order_number": null,
    "status": "PE",
    "status_date": "{{YYYY-MM-DD HH:mm:ss}}",
    "open_date": "{{YYYY-MM-DD HH:mm:ss}}",
    "confirm_date": null,
    "transfer_date": null,
    "amount_br": "99.85",
    "amount_ext": "99.85",
    "amount_iof": "1",
    "amount_ext_requested": "99.85",
    "currency_rate": "1",
    "currency_ext": "PEN",
    "due_date": "{{YYYY-MM-DD HH:mm:ss}}",
    "instalments": "1",
    "payment_type_code": "yape-recurrent",
    "pre_approved": false,
    "capture_available": null,
    "enrollment": {
      "status": "pending",
      "merchant_enrollment_code": "{{unique_enrollment_code}}"
    },
    "redirect_url": "{{redirect_url}}"
  },
  "status": "SUCCESS",
  "redirect_url": "{{redirect_url}}"
}
```

> **Enrollment Status**
> The enrollment remains in a pending state until the customer authorizes it through the Yape app.
> After the status changes, a notification will be sent.
> You can also verify the enrollment status using the Query enrollment status method described above.

> **Payment Status**
> The payment will initially be in **Pending (PE)** status while waiting for the enrollment authorization.
> Once the customer authorizes the enrollment, the payment begins processing. After processing completes, the payment status will change to **Confirmed (CO)** or **Canceled (CA)**, and a notification will be sent.

### Congratulations!

You have successfully integrated **Yape Recurring**.

For more information, refer to the [Direct API reference guide](/api-reference?api=pay-in&page=direct)

## Resources

Use the following resources when testing in your sandbox environment.
- [API Reference](/api-reference)
- [Mock Customer Data](/docs/pay-in/dev-tools/sandbox-simulation/test-customer-data)
- [Error Codes](/docs/pay-in/dev-tools/response-codes/api-error-codes)
## Still need help?

If you still have questions, you can explore the following options:

- **Merchant support:** Contact our support team at [sales.engineering@ebanx.com](mailto:sales.engineering@ebanx.com) for assistance.
- **Not a partner yet?** Complete the [Merchant Signup Form](https://business.ebanx.com/en/request-contact), and our commercial team will reach out to you.
