# Recurring payments

{% hint style="info" %}
**Reach out**

For more details on how to start accepting crypto payments, [get in touch](https://2deywy.share-eu1.hsforms.com/2b92phs9LR_eJdeZoxzmoMA?utm_source=request.network\&utm_medium=docs\&utm_campaign=evergreen\&utm_content=get_in_touch) and we will reach out.
{% endhint %}

## Overview

The Recurring Payments feature allows you to create and manage subscription-like payments on the blockchain. The API handles the scheduling and triggering of these payments, providing a reliable way to automate regular transfers.

## Core functionality

* **Create Recurring Schedules:** Define a payment schedule with a start date, frequency (daily, weekly, monthly, yearly), and total number of payments. The system will generate a payment permit that encapsulates all the payment details.
* **Payer Authorization:** To authorize the payment series, the payer signs the payment permit with an EIP-712 signature. This single authorization allows the system to trigger all subsequent payments in the schedule without further interaction from the payer. For the first payment, the payer may also need to approve a token allowance for the recurring payment contract if they haven't already.
* **Automated Payments:** Once the payer has authorized the schedule, the Request Network API backend systems automatically trigger the payments at the specified intervals. You can rely on the API to handle the entire lifecycle of the recurring payments.
* **Status Tracking and Webhooks:** You can monitor the status of each recurring payment, including processed payments, failures, and completion status (e.g., active, paused, completed). Webhook notifications will be sent for key events like `payment.confirmed` and `payment.failed`, allowing your application to react in real time.
* **Flexible Management:** The API provides the ability to manage the lifecycle of a recurring payment. You can cancel a recurring payment schedule to stop future payments. If a payment fails (e.g., due to insufficient funds), the schedule will be paused, and you can unpause it once the issue is resolved. Unpausing a recurring payment once issues are resolved would allow the subscription to catch up on any missed payments.

## Security & Trust

Our recurring payments feature is built on a non-custodial smart contract that enforces several security measures to protect payers' funds and ensure predictable behavior. The core principle is that all payment parameters are defined upfront and cryptographically signed by the payer, preventing any unauthorized changes.

Here are some key security features provided by the smart contract:

* **Signature-Protected Payments:** Payments cannot be triggered without a valid EIP-712 signature from the payer. The smart contract verifies the signature for every payment attempt.
* **Immutable Recipient:** The recipient's address is part of the signed data. Funds can only be sent to this specified address, which cannot be altered after the schedule is authorized.
* **Fixed Payment Amount:** The amount for each payment is fixed in the signed permit. The smart contract will only transfer this exact amount, preventing any over- or under-payments.
* **Strict Payment Timing:** Payments cannot be triggered before their scheduled time. The contract calculates the due date for each payment and will reject any attempts to trigger it prematurely.
* **No-Repeat Payments:** The contract tracks payments, making it impossible to process the same payment more than once.
* **Enforced Payment Limit:** The total number of payments is defined in the signed permit. The smart contract enforces this limit and will not allow any extra payments beyond the agreed-upon total.
* **Sequential Payments:** Payments must be triggered in a strict, sequential order (e.g., payment #1, then #2, then #3). Any out-of-order attempt will fail, preventing missed or skipped payments from disrupting the schedule.
* **Signature Expiration:** Each recurring payment schedule has a `deadline`. If the signature expires, no further payments can be triggered, providing a hard stop for the agreement.

## Recurring payment workflow

The following diagram illustrates the typical flow for creating and managing recurring payments:

{% @mermaid/diagram content="---
config:
fontSize: 10
sequence:
wrap: true
actorMargin: 50
height: 30
----------

sequenceDiagram
actor User as User (Payer)
participant App
participant API as Request Network API
participant Blockchain

```
App->>API: Create recurring payment schedule
activate API
API-->>App: Returns payment permit for signing
deactivate API

alt If token allowance is needed
    App->>User: Prompt for one-time token allowance approval
    User->>Blockchain: Approves allowance transaction
end

App->>User: Prompt to sign payment permit
User->>App: Provides signature for the permit

App->>API: Submit signed permit to activate schedule
activate API
API-->>App: Confirms activation
deactivate API

loop For each scheduled payment
    API->>Blockchain: Triggers payment automatically
    Blockchain-->>API: Payment result
    API->>App: Webhook notification (payment.confirmed / payment.failed)
end" %}
```

## Supported Networks

Recurring payments are supported on the following Blockchain networks:

* Ethereum
* Polygon
* Arbitrum
* Gnosis
* Base
* Binance Smart Chain
* Sepolia

## Supported currencies

The recurring payments support **all** **ERC20** currencies available in the supported networks.

See the full list here [supported-chains-and-currencies](https://docs.request.network/request-network-api/supported-chains-and-currencies "mention")

## How it works

### 1. Create a recurring payment

To enable recurring payments, a schedule must be created with the following endpoint:

## Initiate a payment

> Initiate a payment without having to create a request first. Supports both one-time and recurring payments. For recurring payments, specify the recurrence object with start date, frequency, total executions, and payer address. The system will create a recurring payment schedule and return the necessary transactions for allowance approval and signature submission. Optionally includes customer information (firstName, lastName, email, address) and a merchant reference field for checkout widget implementations and receipt tracking.

```json
{"openapi":"3.0.0","info":{"title":"Request Network API","version":"0.18.1"},"tags":[{"name":"V2/Payouts","description":"Pay a request without creating one first (V2)"}],"servers":[{"url":"https://api.request.network","description":"Production server"},{"url":"https://api.stage.request.network","description":"Staging server"},{"url":"http://127.0.0.1:8080","description":"Local development server"}],"paths":{"/v2/payouts":{"post":{"description":"Initiate a payment without having to create a request first. Supports both one-time and recurring payments. For recurring payments, specify the recurrence object with start date, frequency, total executions, and payer address. The system will create a recurring payment schedule and return the necessary transactions for allowance approval and signature submission. Optionally includes customer information (firstName, lastName, email, address) and a merchant reference field for checkout widget implementations and receipt tracking.","operationId":"PayoutV2Controller_payRequest_v2","parameters":[{"name":"x-api-key","in":"header","description":"API key for authentication (optional if using Client ID)","required":false,"schema":{"type":"string"}},{"name":"x-client-id","in":"header","description":"Client ID for frontend authentication (optional if using API key)","required":false,"schema":{"type":"string"}},{"name":"Origin","in":"header","description":"Origin header (required for Client ID auth, automatically set by browser)","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"payee":{"type":"string","description":"The wallet address of the payee (Ethereum 0x... or TRON T...)"},"amount":{"type":"string","description":"The payable amount of the invoice, in human readable format"},"invoiceCurrency":{"type":"string","description":"Invoice Currency ID, from the [Request Network Token List](https://docs.request.network/general/request-network-token-list) e.g: USD"},"paymentCurrency":{"type":"string","description":"Payment currency ID, from the [Request Network Token List](https://docs.request.network/general/request-network-token-list) e.g: ETH-sepolia-sepolia"},"feePercentage":{"type":"string","description":"Fee percentage to apply at payment time (e.g., '2.5' for 2.5%)"},"feeAddress":{"type":"string","description":"Address to receive the fee (Ethereum 0x... or TRON T...)"},"recurrence":{"type":"object","properties":{"startDate":{"type":"string","description":"The start date of the payment, cannot be in the past"},"frequency":{"type":"string","enum":["DAILY","WEEKLY","MONTHLY","YEARLY"],"description":"The frequency of the payment"},"totalPayments":{"type":"number","minimum":2,"maximum":256,"description":"The total number of times the payment will be executed (max 256)."},"payer":{"type":"string","description":"The wallet address of the payer. Cannot be the same as the payee address."}},"required":["startDate","frequency","totalPayments","payer"],"description":"Configuration details for recurring payments"},"payerWallet":{"type":"string","description":"The wallet address of the payer, use to check if payer approval exists"},"payerAddress":{"type":"string","description":"The wallet address of the payer (alias for payerWallet)"},"customerInfo":{"type":"object","properties":{"firstName":{"type":"string","minLength":1,"maxLength":100,"description":"Customer's first name"},"lastName":{"type":"string","minLength":1,"maxLength":100,"description":"Customer's last name"},"email":{"type":"string","maxLength":255,"format":"email","description":"Customer's email address"},"address":{"type":"object","properties":{"street":{"type":"string","maxLength":255,"description":"Street address"},"city":{"type":"string","maxLength":100,"description":"City"},"state":{"type":"string","maxLength":100,"description":"State or province"},"postalCode":{"type":"string","maxLength":20,"description":"Postal or ZIP code"},"country":{"type":"string","minLength":2,"maxLength":2,"description":"Country code (ISO 3166-1 alpha-2)"}},"description":"Customer's address"}},"description":"Optional customer information for merchant receipt tracking"},"reference":{"type":"string","minLength":1,"maxLength":255,"description":"Merchant reference for receipt tracking and identification"}},"required":["payee","amount","invoiceCurrency","paymentCurrency"]}}}},"responses":{"201":{"description":"Request created and payment initiated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"requestId":{"type":"string"}},"required":["requestId"]}}}},"404":{"description":"Wallet not found"},"429":{"description":"Too Many Requests"}},"summary":"Initiate a payment","tags":["Pay","V2/Payouts"]}}}}
```

The response includes a payment permit payload (EIP-712 typed data) for signature, and, if required, transactions for token allowance approval.

### 2. Payer authorization

The payer must:

* Approve the recurring payment contract to spend the required amount of tokens (if not already approved)
* Sign the payment permit using EIP-712 compatible wallet

**Example**

```javascript
import { Wallet, providers } from "ethers";

const privateKey = 'WALLET_PRIVATE_KEY'
const provider = const provider = new providers.JsonRpcProvider(
	"RPC_URL",
);

const wallet = new Wallet(privateKey, provider);

const recurringPaymentPermit = ... // from API response
const signature = await wallet._signTypedData(
  recurringPaymentPermit.domain,
  recurringPaymentPermit.types,
  recurringPaymentPermit.values
);

```

### 3. Recurring payment activation

To activate the recurring payment, the resulting signature must be submitted to the following endpoint:

## Submit a recurring payment signature

> Submit a signature for a recurring payment permit to activate the recurring payment schedule. This endpoint is called after creating a recurring payment and obtaining the permit data. The signature authorizes the recurring payment contract to execute payments on behalf of the payer according to the schedule. Once activated, payments will be executed automatically at the specified intervals.

```json
{"openapi":"3.0.0","info":{"title":"Request Network API","version":"0.18.1"},"tags":[{"name":"V2/Payouts","description":"Pay a request without creating one first (V2)"}],"servers":[{"url":"https://api.request.network","description":"Production server"},{"url":"https://api.stage.request.network","description":"Staging server"},{"url":"http://127.0.0.1:8080","description":"Local development server"}],"paths":{"/v2/payouts/recurring/{id}":{"post":{"description":"Submit a signature for a recurring payment permit to activate the recurring payment schedule. This endpoint is called after creating a recurring payment and obtaining the permit data. The signature authorizes the recurring payment contract to execute payments on behalf of the payer according to the schedule. Once activated, payments will be executed automatically at the specified intervals.","operationId":"PayoutV2Controller_submitRecurringPaymentSignature_v2","parameters":[{"name":"id","required":true,"in":"path","description":"The ID of the recurring payment","schema":{"type":"string"}},{"name":"x-api-key","in":"header","description":"API key for authentication (optional if using Client ID)","required":false,"schema":{"type":"string"}},{"name":"x-client-id","in":"header","description":"Client ID for frontend authentication (optional if using API key)","required":false,"schema":{"type":"string"}},{"name":"Origin","in":"header","description":"Origin header (required for Client ID auth, automatically set by browser)","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"permitSignature":{"type":"string","description":"The signature of the recurring payment permit."}},"required":["permitSignature"]}}}},"responses":{"201":{"description":"Recurring payment signature submitted successfully","content":{"application/json":{}}},"400":{"description":"Bad request","content":{"application/json":{}}},"404":{"description":"Recurring payment not found"},"429":{"description":"Too Many Requests"}},"summary":"Submit a recurring payment signature","tags":["Pay","V2/Payouts"]}}}}
```

A successful response confirms activation. The schedule is now active and payments will be executed automatically.

### 4. Status monitoring

The status, processed payments, next payment date, and other details can be retrieved at any time.

## Get the status of a recurring payment

> Retrieve the current status and execution details of a recurring payment. Returns information about executed payments, remaining executions, next payment date, and overall status. This endpoint is useful for monitoring recurring payment progress and checking if payments are being executed as expected. Note: Customer information (PII) is not included in the response for security reasons.

```json
{"openapi":"3.0.0","info":{"title":"Request Network API","version":"0.18.1"},"tags":[{"name":"V2/Payouts","description":"Pay a request without creating one first (V2)"}],"servers":[{"url":"https://api.request.network","description":"Production server"},{"url":"https://api.stage.request.network","description":"Staging server"},{"url":"http://127.0.0.1:8080","description":"Local development server"}],"paths":{"/v2/payouts/recurring/{id}":{"get":{"description":"Retrieve the current status and execution details of a recurring payment. Returns information about executed payments, remaining executions, next payment date, and overall status. This endpoint is useful for monitoring recurring payment progress and checking if payments are being executed as expected. Note: Customer information (PII) is not included in the response for security reasons.","operationId":"PayoutV2Controller_getRecurringPaymentStatus_v2","parameters":[{"name":"id","required":true,"in":"path","description":"The ID of the recurring payment","schema":{"type":"string"}},{"name":"x-api-key","in":"header","description":"API key for authentication (optional if using Client ID)","required":false,"schema":{"type":"string"}},{"name":"x-client-id","in":"header","description":"Client ID for frontend authentication (optional if using API key)","required":false,"schema":{"type":"string"}},{"name":"Origin","in":"header","description":"Origin header (required for Client ID auth, automatically set by browser)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Recurring payment status retrieved successfully","content":{"application/json":{}}},"404":{"description":"Recurring payment not found","content":{"application/json":{}}},"429":{"description":"Too Many Requests"}},"summary":"Get the status of a recurring payment","tags":["Pay","V2/Payouts"]}}}}
```

### 5. Recurring payment management

Recurring payments can be `cancelled` or `unpaused`.

* **Cancel**: stops all future payments
* **Unpause**: resume the recurring payment after it fails three times (due to insufficient balance or allowance)\\

## Update a recurring payment

> Update a recurring payment by cancelling it or unpausing it. When cancelling, optionally returns a transaction to decrease allowance. When unpausing, resumes execution of a paused recurring payment.

```json
{"openapi":"3.0.0","info":{"title":"Request Network API","version":"0.18.1"},"tags":[{"name":"V2/Payouts","description":"Pay a request without creating one first (V2)"}],"servers":[{"url":"https://api.request.network","description":"Production server"},{"url":"https://api.stage.request.network","description":"Staging server"},{"url":"http://127.0.0.1:8080","description":"Local development server"}],"paths":{"/v2/payouts/recurring/{id}":{"patch":{"description":"Update a recurring payment by cancelling it or unpausing it. When cancelling, optionally returns a transaction to decrease allowance. When unpausing, resumes execution of a paused recurring payment.","operationId":"PayoutV2Controller_updateRecurringPayment_v2","parameters":[{"name":"id","required":true,"in":"path","description":"The ID of the recurring payment","schema":{"type":"string"}},{"name":"x-api-key","in":"header","description":"API key for authentication (optional if using Client ID)","required":false,"schema":{"type":"string"}},{"name":"x-client-id","in":"header","description":"Client ID for frontend authentication (optional if using API key)","required":false,"schema":{"type":"string"}},{"name":"Origin","in":"header","description":"Origin header (required for Client ID auth, automatically set by browser)","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"action":{"type":"string","enum":["cancel","unpause"],"description":"The action to perform on the recurring payment"}},"required":["action"]}}}},"responses":{"200":{"description":"Recurring payment updated successfully","content":{"application/json":{}}},"400":{"description":"Bad request","content":{"application/json":{}}},"404":{"description":"Recurring payment not found"},"429":{"description":"Too Many Requests"}},"summary":"Update a recurring payment","tags":["Pay","V2/Payouts"]}}}}
```
