9.0 KiB
Gift Subscriptions API Documentation
Overview
The Gift Subscriptions feature allows users to purchase subscription gifts that can be redeemed by other users, enabling social gifting and subscription sharing within the DysonNetwork platform.
If you use it through the gateway, the /api
should be replaced with the /id
Key Features
- Purchase Gifts: Users can buy subscriptions as gifts for specific recipients or as open gifts
- Gift Codes: Each gift has a unique redemption code
- Flexible Redemption: Open gifts can be redeemed by anyone, while targeted gifts are recipient-specific
- Security: Prevents duplicate subscriptions and enforces account level requirements
- Integration: Full integration with existing subscription, coupon, and pricing systems
- Clean User Experience: Unpaid gifts are hidden from users and automatically cleaned up
- Automatic Maintenance: Old unpaid gifts are removed after 24 hours
API Endpoints
All endpoints are authenticated and require a valid user session. The base path for gift endpoints is /api/gifts
.
1. List Sent Gifts
Retrieve gifts you have purchased.
GET /api/gifts/sent?offset=0&take=20
Authorization: Bearer <token>
Response: Array of SnWalletGift
objects
2. List Received Gifts
Retrieve gifts sent to you or redeemed by you (for open gifts).
GET /api/gifts/received?offset=0&take=20
Authorization: Bearer <token>
Response: Array of SnWalletGift
objects
3. Get Specific Gift
Retrieve details for a specific gift.
GET /api/gifts/{giftId}
Authorization: Bearer <token>
Parameters:
giftId
: GUID of the gift
Response: SnWalletGift
object
4. Check Gift Code
Validate if a gift code can be redeemed by the current user.
GET /api/gifts/check/{giftCode}
Authorization: Bearer <token>
Response:
{
"gift_code": "ABCD1234EFGH",
"subscription_identifier": "basic",
"can_redeem": true,
"error": null,
"message": "Happy birthday!"
}
5. Purchase a Gift
Create and purchase a gift subscription.
POST /api/gifts/purchase
Authorization: Bearer <token>
Content-Type: application/json
{
"subscription_identifier": "premium",
"recipient_id": "550e8400-e29b-41d4-a716-446655440000", // Optional: null for open gifts
"payment_method": "in_app_wallet",
"payment_details": {
"currency": "irl"
},
"message": "Enjoy your premium subscription!", // Optional
"coupon": "SAVE20", // Optional
"gift_duration_days": 30, // Optional: defaults to 30
"subscription_duration_days": 30 // Optional: defaults to 30
}
Response: SnWalletGift
object
6. Redeem a Gift
Redeem a gift code to create a subscription for yourself.
POST /api/gifts/redeem
Authorization: Bearer <token>
Content-Type: application/json
{
"gift_code": "ABCD1234EFGH"
}
Response:
{
"gift": { ... },
"subscription": { ... }
}
7. Mark Gift as Sent
Mark a gift as sent (ready for redemption).
POST /api/gifts/{giftId}/send
Authorization: Bearer <token>
Parameters:
giftId
: GUID of the gift to mark as sent
8. Cancel a Gift
Cancel a gift before it has been redeemed.
POST /api/gifts/{giftId}/cancel
Authorization: Bearer <token>
Parameters:
giftId
: GUID of the gift to cancel
Usage Examples
Client Implementation
Here are examples showing how to integrate gift subscriptions into your client application.
Example 1: Purchase a Gift for a Specific User
async function purchaseGiftForFriend(subscriptionId, friendId, message) {
const response = await fetch('/api/gifts/purchase', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
subscription_identifier: subscriptionId,
recipient_id: friendId,
payment_method: 'in_app_wallet',
payment_details: { currency: 'irl' },
message: message
})
});
const gift = await response.json();
return gift.gift_code; // Share this code with the friend
}
Example 2: Create an Open Gift
async function createOpenGift(subscriptionId) {
const response = await fetch('/api/gifts/purchase', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
subscription_identifier: subscriptionId,
payment_method: 'in_app_wallet',
payment_details: { currency: 'irl' },
message: 'Redeem this anywhere!'
// No recipient_id makes it an open gift
})
});
const gift = await response.json();
// Mark as sent to make it redeemable
await markGiftAsSent(gift.id);
return gift;
}
Example 3: Redeem a Gift Code
async function redeemGiftCode(giftCode) {
// First, check if the gift can be redeemed
const checkResponse = await fetch(`/api/gifts/check/${giftCode}`, {
headers: {
'Authorization': `Bearer ${token}`
}
});
const checkResult = await checkResponse.json();
if (!checkResult.canRedeem) {
throw new Error(checkResult.error);
}
// If valid, redeem it
const redeemResponse = await fetch('/api/gifts/redeem', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
gift_code: giftCode
})
});
const result = await redeemResponse.json();
return result.subscription; // The newly created subscription
}
Example 4: Display User's Gift History
async function getGiftHistory() {
// Get gifts I sent
const sentResponse = await fetch('/api/gifts/sent', {
headers: { 'Authorization': `Bearer ${token}` }
});
const sentGifts = await sentResponse.json();
// Get gifts I received
const receivedResponse = await fetch('/api/gifts/received', {
headers: { 'Authorization': `Bearer ${token}` }
});
const receivedGifts = await receivedResponse.json();
return { sent: sentGifts, received: receivedGifts };
}
Gift Status Lifecycle
Gifts follow this status lifecycle:
- Created: Initially purchased, can be cancelled or marked as sent
- Note: Gifts in "Created" status are not visible to users and are automatically cleaned up after 24 hours if unpaid
- Sent: Made available for redemption, can be cancelled
- Redeemed: Successfully redeemed, creates a subscription
- Cancelled: Permanently cancelled, refund may be processed
- Expired: Expired without redemption
Automatic Maintenance
The system includes automatic cleanup to maintain data integrity:
- Unpaid Gift Cleanup: Gifts that remain in "Created" status (unpaid) for more than 24 hours are automatically removed from the database
- User Visibility: Only gifts that have been successfully paid and sent are visible in user gift lists
- Background Processing: Cleanup runs hourly via scheduled jobs
This ensures a clean user experience while preventing accumulation of abandoned gift purchases.
Validation Rules
Purchase Validation
- Subscription must exist and be valid
- If coupon provided, it must be valid and applicable
- Recipient account must exist (if specified)
- User must meet level requirements for the subscription
Redemption Validation
- Gift code must exist
- Gift must be in "Sent" status
- Gift must not be expired
- User must meet level requirements
- User must not already have an active subscription of the same type
- For targeted gifts, user must be the specified recipient
Pricing & Payments
Gifts use the same pricing system as regular subscriptions:
- Base price from subscription template
- Coupon discounts applied
- Currency conversion as needed
- Payment processing through existing payment methods
Notification Events
The system sends push notifications for:
- gifts.redeemed: When someone redeems your gift
- gifts.claimed: When the recipient redeems your targeted gift
Notifications include gift and subscription details for rich UI updates.
Error Handling
Common error responses:
400 Bad Request
: Invalid parameters, validation failures401 Unauthorized
: Missing or invalid authentication403 Forbidden
: Insufficient permissions404 Not Found
: Gift or subscription not found409 Conflict
: Business logic violations (duplicate subscriptions, etc.)
Integration Notes
Database Schema
The feature adds a wallet_gifts
table with relationships to:
accounts
(gifter, recipient, redeemer)wallet_subscriptions
(created subscription)wallet_coupons
(applied discounts)
Backwards Compatibility
- No changes to existing subscription endpoints
- New gift-related endpoints are additive
- Existing payment flows remain unchanged
Performance Considerations
- Gift codes are indexed for fast lookups
- Status filters optimize database queries
- Caching integrated with existing subscription caching
Support
For implementation questions or issues, refer to the DysonNetwork API documentation or contact the development team.