Revert Points
Return points to a user's account when a redemption fails or needs to be reversed.
↩️
This API is called when YGG needs to reverse a previous deduction due to errors, timeouts, or other redemption failures.
Endpoint Details
- Method:
POST - Path:
/revert-deduct-points - Content-Type:
application/json
POST https://partner-api.example.com/revert-deduct-pointsRequest Format
Headers
| Header | Description | Example |
|---|---|---|
X-API-KEY | Your API key | your_api_key |
X-API-REQUEST | Unique UUID v7 | 01987d64-6519-747b-9200-beba98700464 |
X-API-SIGNATURE | HMAC signature | 92aa703cc483ea2cc90488c05e699179... |
Content-Type | Must be application/json | application/json |
Request Body
{
"yggRedemptionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"partnerTransactionId": "txn_1234567890",
"address": "0xabcd....a",
"deductPoints": 1000,
"revertReason": "Timeout: User has not claimed redemption in time"
}| Field | Type | Required | Description |
|---|---|---|---|
yggRedemptionId | string | ✅ | Original YGG redemption UUID |
partnerTransactionId | string | ✅ | Your transaction ID from deduction |
address | string | ✅ | User's wallet address |
deductPoints | integer | ✅ | Original deduction amount |
revertReason | string | ✅ | Reason for the reversion |
Response Format
Success Response
HTTP Status: 200 OK
{
"success": true,
"partnerTransactionId": "txn_1234567890",
"partnerRevertId": "revert_9876543210"
}Required Fields
| Field | Type | Description |
|---|---|---|
success | boolean | Must be true |
partnerTransactionId | string | Original transaction ID |
partnerRevertId | string | New ID for the revert transaction |
🏷️
Best Practice: Generate a unique partnerRevertId to track the points restoration transaction separately.
Common Revert Reasons
| Reason | Description |
|---|---|
Timeout: User has not claimed redemption in time | User didn't claim within time limit |
Transaction failed: Insufficient gas | Blockchain transaction failed |
Transaction failed: Network congestion | Network issues prevented completion |
User cancelled redemption | User explicitly cancelled |
System error during processing | Internal YGG system error |
Implementation Guidelines
Validation Steps
- Verify original transaction exists
- Check transaction hasn't been reverted already
- Validate the revert amount matches original deduction
- Add points back to user account
- Record the reversion with unique ID
⚠️
Important: Ensure the revert operation is idempotent. Multiple calls with the same yggRedemptionId should not duplicate the points restoration.
Example Implementation
app.post('/revert-deduct-points', async (req, res) => {
try {
// Validate authentication
if (!validateAuth(req.headers)) {
return res.json({
success: false,
errorCode: 'ERR-AUTH-FAILED',
errorMessage: 'Authentication failed'
});
}
const {
yggRedemptionId,
partnerTransactionId,
address,
deductPoints,
revertReason
} = req.body;
// Find original transaction
const originalTxn = await findTransactionById(partnerTransactionId);
if (!originalTxn) {
return res.json({
success: false,
errorCode: 'ERR-TRANSACTION-NOT-FOUND',
errorMessage: 'Original transaction not found'
});
}
// Check if already reverted
if (originalTxn.status === 'reverted') {
return res.json({
success: false,
errorCode: 'ERR-ALREADY-REVERTED',
errorMessage: 'Transaction already reverted'
});
}
// Validate amounts match
if (originalTxn.points !== deductPoints) {
return res.json({
success: false,
errorCode: 'ERR-INVALID-AMOUNT',
errorMessage: 'Revert amount does not match original'
});
}
// Perform reversion
const revertId = await revertUserPoints(
originalTxn.user_id,
deductPoints,
yggRedemptionId,
revertReason
);
// Mark original transaction as reverted
await markTransactionReverted(partnerTransactionId);
res.json({
success: true,
partnerTransactionId: partnerTransactionId,
partnerRevertId: revertId
});
} catch (error) {
res.json({
success: false,
errorCode: 'ERR-INTERNAL',
errorMessage: 'Internal server error'
});
}
});Database Schema Example
-- Track revert transactions separately
CREATE TABLE point_reversions (
id SERIAL PRIMARY KEY,
original_transaction_id VARCHAR(50) NOT NULL,
ygg_redemption_id VARCHAR(36) NOT NULL,
user_id INTEGER NOT NULL,
points INTEGER NOT NULL,
revert_reason TEXT NOT NULL,
partner_revert_id VARCHAR(50) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT NOW(),
FOREIGN KEY (original_transaction_id)
REFERENCES point_transactions(partner_transaction_id)
);
-- Update original transaction status
UPDATE point_transactions
SET status = 'reverted',
updated_at = NOW()
WHERE partner_transaction_id = ?;📊
Audit Trail: Maintain detailed logs of all reversions for regulatory compliance and debugging.