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
| Status | Description | Deduction Allowed |
|---|---|---|
INIT | Sign request created, waiting for user scan | No |
PENDING | User scanned, waiting to complete verification | No |
SIGNED | Agreement active | Yes |
SUSPENDED | Temporarily paused (can be resumed) | No |
UNSIGNED | Agreement terminated (final) | No |
EXPIRED | Agreement expired (final) | No |
REJECTED | User actively canceled signing (final) | No |
FAILED | Sign failed (final) | No |
TIMEOUT | Sign 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 Name | Method | Endpoint | Description |
|---|---|---|---|
| Sign Request | POST | /v5/pay/agreement/sign | Create sign request, get QR code |
| Unsign | POST | /v5/pay/agreement/unsign | Terminate agreement |
| Deduction | POST | /v5/pay/agreement/deduction | Execute automatic deduction |
| Pay with Sign | POST | /v5/pay/agreement/pay-with-sign | Sign + Pay in one step |
| Refund | POST | /v5/pay/agreement/refund | Refund deduction transaction |
| Query Agreement | GET | /v5/pay/agreement/query | Query single agreement status |
| List Agreements | GET | /v5/pay/agreement/list | List merchant agreements |
| Query Transaction | GET | /v5/pay/agreement/transaction/query | Query single transaction/refund |
| List Transactions | GET | /v5/pay/agreement/transaction/list | List 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"
}
Related Documentation
- Common Specifications - Request headers, response format, rate limits
- Webhooks - Async notification handling
- Error Codes - Error code reference
- Appendix - Scene codes, currencies, sandbox testing