Payment Cards
Manage user payment cards and perform deposits from cards to Paysera accounts.
This feature requires special permissions and the cards OAuth scope to manage user payment cards.
What are Payment Cards?
Payment Cards in Wallet API allow users to:
- 💳 Link payment cards to their Paysera accounts
- 💰 Deposit funds from cards to accounts
- 🔗 Manage card-account relationships
- 📊 Track card status and commissions
Key Concepts
Card Statuses
| Status | Description | Actions Available |
|---|---|---|
unrelated | Card created but not verified | Edit, Delete, Relate |
related | Card verified and ready to use | Edit, Delete, Deposit |
failed | Card verification failed | Delete only |
Card Lifecycle
Required Permissions
OAuth Scope
cards - Required to manage user's payment cards
Client Permissions
Special client permissions must be granted by Paysera support to use Payment Cards API.
Main Features
1. Card Management
Create Cards:
- Link new payment cards to accounts
- Initiate card verification process
- Set card-account relationships
Edit Cards:
- Update card-account links
- Change card priority order
Delete Cards:
- Remove cards from system
- Available for all statuses
2. Card Verification
When a card is created, it starts with unrelated status:
- Create card via API
- Redirect user to verification page
- User enters card details securely
- Processing partner verifies card
- Status updates to
relatedorfailed
Card verification is asynchronous. Poll the card status to check when verification completes.
3. Card Deposits
Transfer funds from verified cards to Paysera accounts:
Process:
- Create deposit request
- Specify amount and target account
- Process the deposit
- Commission is automatically calculated
Commission:
- Charged on top of deposit amount
- Based on commission rules
- Varies by card type and amount
Quick Start Example
Basic Card Flow
import PayseraWalletClient from 'paysera-wallet-api';
const client = new PayseraWalletClient({
accessToken: 'your_access_token_with_cards_scope'
});
async function linkNewCard(userId, accountNumber) {
try {
// 1. Create card
const card = await client.createCard({
user_id: userId,
accounts: [{
number: accountNumber,
order: 1
}],
relation: {
redirect_back_uri: 'https://example.com/card-linked'
}
});
console.log('Card created:', card.id);
console.log('Redirect user to:', card.relation.redirect_uri);
// 2. Wait for user to complete verification
// (User is redirected, enters card details)
// 3. Poll for status
const relatedCard = await waitForCardRelation(card.id);
console.log('✅ Card verified and ready!');
return relatedCard;
} catch (error) {
console.error('Card setup failed:', error);
throw error;
}
}
async function waitForCardRelation(cardId, maxAttempts = 10) {
for (let i = 0; i < maxAttempts; i++) {
const card = await client.getCard(cardId);
if (card.status === 'related') {
return card;
}
if (card.status === 'failed') {
throw new Error('Card verification failed');
}
// Wait 2 seconds before next check
await new Promise(resolve => setTimeout(resolve, 2000));
}
throw new Error('Card verification timeout');
}
Card-Account Relationships
Priority Ordering
Cards can be linked to multiple accounts with priority order:
{
"accounts": [
{
"number": "EVP1234567890",
"order": 1 // Primary account
},
{
"number": "EVP9876543210",
"order": 2 // Backup account
}
]
}
Usage:
- Lower order number = higher priority
- Used for automatic deposits
- Can be updated anytime
Commission Structure
How Commissions Work
Commissions are charged when depositing from cards:
Formula:
Total Charge = Deposit Amount + Commission
Commission = max(min_commission, Deposit × percent + fixed_amount)
Example:
// Commission rule: 2% + €0.10, min €0.50
Deposit: €10.00
Commission: max(€0.50, €10.00 × 2% + €0.10) = €0.50
Total charged from card: €10.50
Commission Fields
| Field | Description |
|---|---|
percent | Percentage fee (e.g., 2 for 2%) |
fix | Fixed fee in cents |
min | Minimum commission in cents |
max | Maximum commission in cents |
currency | Commission currency |
Security Considerations
Sensitive Data
🔒 Card details are NEVER sent to your server:
- User enters card info on secure verification page
- Processing partner handles card data
- Your API only receives card ID and status
Best Practices
- Use HTTPS for all redirect URIs
- Validate card status before deposits
- Handle verification failures gracefully
- Don't store card numbers (use API IDs)
- Implement timeouts for verification polling
Common Use Cases
Use Case 1: Account Top-Up
Allow users to add funds to their Paysera account:
async function topUpAccount(cardId, accountNumber, amount) {
// Ensure card is related
const card = await client.getCard(cardId);
if (card.status !== 'related') {
throw new Error('Card not verified');
}
// Create deposit
const deposit = await client.createDeposit(cardId, {
account_number: accountNumber,
amount: {
amount: amount * 100, // Convert to cents
currency: 'EUR'
}
});
console.log(`Amount: €${deposit.amount.amount_decimal}`);
console.log(`Commission: €${deposit.commission.amount_decimal}`);
console.log(`Total: €${(parseFloat(deposit.amount.amount_decimal) +
parseFloat(deposit.commission.amount_decimal)).toFixed(2)}`);
// Process deposit
await client.processDeposit(deposit.id);
console.log('✅ Funds deposited successfully');
}
Use Case 2: Recurring Payments
Set up automatic recurring deposits:
class RecurringDeposit {
constructor(client, cardId, accountNumber) {
this.client = client;
this.cardId = cardId;
this.accountNumber = accountNumber;
}
async scheduleMonthly(amount) {
// Run on 1st of every month
const schedule = '0 0 1 * *'; // Cron format
// In production, use proper job scheduler
setInterval(async () => {
try {
await this.makeDeposit(amount);
} catch (error) {
console.error('Recurring deposit failed:', error);
await this.notifyUser(error);
}
}, 30 * 24 * 60 * 60 * 1000); // 30 days
}
async makeDeposit(amount) {
const deposit = await this.client.createDeposit(this.cardId, {
account_number: this.accountNumber,
amount: {
amount: amount * 100,
currency: 'EUR'
}
});
await this.client.processDeposit(deposit.id);
console.log(`Monthly deposit of €${amount} completed`);
}
}
Use Case 3: Multiple Cards Management
Let users manage multiple payment cards:
class CardManager {
constructor(client, userId) {
this.client = client;
this.userId = userId;
}
async listCards() {
const response = await this.client.getCards({
user_id: this.userId,
limit: 50
});
return response.cards.map(card => ({
id: card.id,
type: card.card_data?.type || 'Unknown',
number: card.card_data?.number || '****',
status: card.status,
isDefault: card.accounts?.[0]?.order === 1
}));
}
async setDefaultCard(cardId, accountNumber) {
// Get all user cards
const allCards = await this.listCards();
// Update orders
for (const card of allCards) {
const newOrder = card.id === cardId ? 1 :
(card.isDefault ? 2 : card.order + 1);
await this.client.editCard(card.id, {
accounts: [{
number: accountNumber,
order: newOrder
}]
});
}
console.log(`Card ${cardId} is now default`);
}
async removeCard(cardId) {
await this.client.deleteCard(cardId);
console.log(`Card ${cardId} removed`);
}
}
API Endpoints Overview
Card Management
| Endpoint | Method | Description |
|---|---|---|
/rest/v1/card | POST | Create new card |
/rest/v1/card/{id} | GET | Get card details |
/rest/v1/card/{id} | PUT | Edit card |
/rest/v1/card/{id} | DELETE | Delete card |
/rest/v1/cards | GET | List user's cards |
Deposits
| Endpoint | Method | Description |
|---|---|---|
/rest/v1/card/{id}/deposit | POST | Create deposit |
/rest/v1/deposit/{id}/process | PUT | Process deposit |
Error Handling
Common Errors
| Error | Cause | Solution |
|---|---|---|
unauthorized | Missing cards scope | Request proper scope |
forbidden | No card management permissions | Contact support |
not_found | Invalid card ID | Verify card exists |
invalid_state | Card status doesn't allow action | Check card status first |
Example Error Handling
async function safeDeposit(cardId, depositData) {
try {
// Check card status
const card = await client.getCard(cardId);
if (card.status !== 'related') {
throw new Error(`Card is ${card.status}, cannot deposit`);
}
// Create and process deposit
const deposit = await client.createDeposit(cardId, depositData);
await client.processDeposit(deposit.id);
return deposit;
} catch (error) {
if (error.code === 'not_found') {
console.error('Card not found');
} else if (error.code === 'invalid_state') {
console.error('Card verification incomplete');
} else if (error.code === 'insufficient_funds') {
console.error('Card has insufficient funds');
} else {
console.error('Deposit failed:', error.message);
}
throw error;
}
}
Next Steps
- 💳 Managing Cards - Create, edit, delete cards
- 💰 Card Deposits - Deposit from cards to accounts
- 🔐 Authentication - Setup OAuth
- 📖 API Reference - Complete API docs
Need Help?
- API Support: tech_support@paysera.com
- Request Access: Contact support to enable payment cards feature
- Security Questions: tech_support@paysera.com