Skip to main content

Recurring Payments Introduction

Note

This API is not yet publicly available. Please contact Bybit Pay team if you need access to Recurring Payments.

Overview​

Recurring Payments (Auto-deduction) enables merchants to automatically deduct funds from users' Bybit accounts after users pre-authorize the agreement. No manual confirmation is required for each transaction.

Document Version: v2.11

Update History:

  • v2.11 (2026-06-09): Added REJECTED agreement status (user actively canceled signing); Sign-with-pay Webhook changed to independent notifications to signNotifyUrl/payNotifyUrl; Added sign rejected notification (eventType=REJECTED) and sign failed notification (eventType=AGREEMENT_SIGN_RESULT); Added EXPIRED event type; Fixed timeout handling description (timeout does send Webhook notification); Completed all eventType enum tables
  • v2.10 (2026-03-29): Added merchant settlement configuration error code MERCHANT_SETTLEMENT_CONFIG_ERROR (139006004); Added merchant quota limit error code EXCEED_MERCHANT_QUOTA_LIMIT (139004008); Added chainAddress field to amount and limit config in sign/deduction/sign-and-pay APIs
  • v2.9 (2026-02-24): Added Agreement Type Description section detailing usage scenarios and limit configuration differences for CYCLE/NON_CYCLE/SINGLE types; Fixed missing NON_CYCLE in documentation
  • v2.8 (2026-02-11): Expanded deduction API supported scene codes from 6 to 17, added FOOD, ENTERTAINMENT, EDUCATION, MEMBERSHIP, RENT, FITNESS, TELECOM, CLOUD, INSURANCE, LOAN, OTHERS
  • v2.7: Updated response format (retCode/retMsg/result), fixed field type descriptions, adjusted document structure

Applicable Scenarios:

  • Ride-hailing contactless payment
  • Membership auto-renewal / Subscriptions
  • Utility bill payment
  • Parking lot automatic deduction
  • Recurring service payments

Security Mechanism:

  • Strong authentication for signing (SMS/Face/Password)
  • Single and period limit controls
  • Real-time risk control interception
  • Async notification for every deduction

Core Concepts​

Agreement Lifecycle​

                                    ┌─────────────────────────────────────┐
│ │
▼ │
┌──────┐ Sign Request ┌──────┐ User Scan ┌─────────┐ Confirm Sign ┌────────┐
│ │ ─────────────→ │ │ ───────────→ │ │ ─────────────→ │ │
│ Start│ │ INIT │ │ PENDING │ │ SIGNED │◀──┐
│ │ │ │ │ │ │ │ │
└──────┘ └──────┘ └─────────┘ └────────┘ │
│ │ │ │ │ │ │ │
│ Timeout(30min) │ │ │ Sign Failed │ │ │ │
▼ │ ▼ │ │ │ │ │
┌─────────┐ ┌────────┐│ │ │ │ │
│ TIMEOUT │ │ FAILED ││ │ │ │ │
└─────────┘ └────────┘│ │ │ │ │
│ User Rejected │ │ │ │
▼ │ │ │ │
┌──────────┐ │ │ │ │
│ REJECTED │ │ │ │ │
└──────────┘ │ │ │ │
│ │ │ │
┌──────────────────────────────────────────────┘ │ │ │
│ Unsign │ │ │
▼ │ │ │
┌──────────┐ │ │ │
│ UNSIGNED │ │ │ │
└──────────┘ │ │ │
│ │ │
┌────────────────────────────────────────────────┘ │ │
│ Expired │ │
▼ │ │
┌─────────┐ │ │
│ EXPIRED │ │ │
└─────────┘ │ │
│ │
┌───────────────────────────────────────────────────┘ │
│ Risk/Abnormal │
▼ │
┌───────────┐ Resume │
│ SUSPENDED │ ────────────────────────────────────────────────┘
└───────────┘

Agreement States​

StatusDescriptionDeduction Allowed
INITSign request created, waiting for user scanNo
PENDINGUser scanned, waiting to complete verificationNo
SIGNEDAgreement activeYes
SUSPENDEDTemporarily paused (can be resumed)No
UNSIGNEDAgreement terminated (final)No
EXPIREDAgreement expired (final)No
REJECTEDUser actively canceled signing (final)No
FAILEDSign failed (final)No
TIMEOUTSign link expired (final)No

Integration Flow​

1. Sign Flow (One-time Setup)​

Merchant Server                  Platform                         User App
│ │ │
│ 1.Sign Request │ │
│ (userId + │ │
│ merchantUserId) │ │
│ ──────────────────────→ │ │
│ │ │
│ 2.Return Sign QR Code │ │
│ (qrCode/signUrl) │ │
│ ←────────────────────── │ │
│ │ │
│ Display QR Code │ 3.Scan │
│ - - - - - - - - - - - - │ ←──────────────────────── │
│ │ │
│ │ 4.Login/Register │
│ │ ←─────────────────────────→│
│ │ │
│ │ 5.Identity Verification│
│ │ (SMS/Face/Password) │
│ │ ←─────────────────────────→│
│ │ │
│ │ 6.Confirm Sign Auth │
│ │ ←──────────────────────── │
│ │ │
│ 7.Webhook Notification │ │
│ (agreementNo) │ │
│ ←────────────────────── │ │
│ │ │

2. Deduction Flow (Automatic Payment)​

Merchant Server → Deduction Request(agreementNo) → Platform
↓
┌─────────────────┐
│ 1. Agreement │
│ validity check│
│ 2. Limit check │
│ 3. Risk check │
│ 4. Execute │
│ deduction │
└─────────────────┘
↓
←←←←←←← Sync return result + Async notification ←←←←

User receives deduction notification (Push/SMS)

3. Refund Flow​

Merchant Server → Refund Request(tradeNo + refundAmount) → Platform
↓
┌─────────────────┐
│ 1. Transaction │
│ validity check│
│ 2. Refundable │
│ amount check │
│ 3. Execute refund│
└─────────────────┘
↓
←←←←←←← Sync return result + Async notification ←←←←←←←←

User receives refund notification (Push/SMS)

API List​

API NameMethodEndpointDescription
Sign RequestPOST/v5/pay/agreement/signCreate sign request, get QR code
UnsignPOST/v5/pay/agreement/unsignTerminate agreement
DeductionPOST/v5/pay/agreement/deductionExecute automatic deduction
Pay with SignPOST/v5/pay/agreement/pay-with-signSign + Pay in one step
RefundPOST/v5/pay/agreement/refundRefund deduction transaction
Query AgreementGET/v5/pay/agreement/queryQuery single agreement status
List AgreementsGET/v5/pay/agreement/listList merchant agreements
Query TransactionGET/v5/pay/agreement/transaction/queryQuery single transaction/refund
List TransactionsGET/v5/pay/agreement/transaction/listList transactions under agreement

Quick Start​

Step 1: Create Sign Request​

POST /v5/pay/agreement/sign
{
"merchantId": "M123456789",
"agreementType": "CYCLE",
"merchantUserId": "merchant_user_123",
"sceneCode": "SUBSCRIPTION",
"externalAgreementNo": "MERCHANT_AGR_001",
"singleLimit": {
"amount": "100000",
"currency": "USDT",
"currencyType": "CRYPTO"
},
"notifyUrl": "https://merchant.com/notify/sign"
}

Step 2: User Completes Sign​

Display the returned qrCode or signUrl to the user. User scans and completes identity verification.

Step 3: Receive Sign Webhook​

{
"notifyType": "AGREEMENT_STATUS",
"data": {
"eventType": "SIGNED",
"agreementNo": "AGR202312230001",
"status": "SIGNED",
"userId": "U_123456789"
}
}

Step 4: Execute Deduction​

POST /v5/pay/agreement/deduction
{
"merchantId": "M123456789",
"userId": "U_123456789",
"agreementType": "CYCLE",
"agreementNo": "AGR202312230001",
"outTradeNo": "ORDER20231223001",
"sceneCode": "SUBSCRIPTION",
"amount": {
"total": "2350",
"currency": "USDT",
"currencyType": "CRYPTO",
"chain": "TRC20"
},
"orderInfo": {
"orderTitle": "Monthly subscription"
},
"notifyUrl": "https://merchant.com/notify/pay"
}