Skip to main content

Cash-in with Code

Accept cash from customers and deposit it into their Paysera wallet using a cash-in code.

Use Case Overview

Customer provides cash, you scan their cash-in code and deposit funds into their wallet using background payment with allowance.


Implementation Steps

1. Extract Wallet ID from Code

Cash-in code format: EVP000000000001 (wallet ID padded with zeros to 12 characters)

function extractWalletId(cashInCode) {
const paddedId = cashInCode.replace(/^EVP/, '');
const walletId = parseInt(paddedId, 10);
return walletId;
}

// Example: EVP000000014471 → 14471

2. Create Transaction with Allowance

Allowance Provided by Paysera

Paysera provides the allowance for cash-in operations. You don't need to create one.

Request:

POST /rest/v1/transaction HTTP/1.1
Host: wallet.paysera.com
Content-Type: application/json
Authorization: MAC id="...", ...

{
"payments": [
{
"description": "Cash deposit",
"price": 5000,
"currency": "EUR"
}
],
"allowance": {
"id": 784,
"optional": true
}
}

Response:

{
"transaction_key": "pDAlAZ3z",
"status": "new",
"payments": [
{
"id": 2988,
"price": 5000,
"currency": "EUR",
"price_decimal": "50.00"
}
],
"allowance": {
"optional": true,
"data": {
"id": 784,
"max_price": 1500
}
}
}

3. Reserve Transaction with Wallet

Request:

PUT /rest/v1/transaction/pDAlAZ3z/reserve/14471 HTTP/1.1
Host: wallet.paysera.com
Authorization: MAC id="...", ...

Response:

{
"transaction_key": "pDAlAZ3z",
"status": "reserved",
"type": "automatic",
"wallet": 14471,
"payments": [
{
"id": 2988,
"status": "reserved",
"price_decimal": "50.00",
"wallet": 14471
}
]
}

4. Confirm Transaction

Request:

PUT /rest/v1/transaction/pDAlAZ3z/confirm HTTP/1.1
Host: wallet.paysera.com
Authorization: MAC id="...", ...

Response:

{
"transaction_key": "pDAlAZ3z",
"status": "confirmed",
"confirmed_at": 1355314392,
"wallet": 14471,
"payments": [
{
"id": 2988,
"status": "confirmed",
"confirmed_at": 1355314392,
"price_decimal": "50.00"
}
]
}

Complete Example

async function processCashIn(cashInCode, amount, allowanceId) {
// 1. Extract wallet ID from code
const walletId = extractWalletId(cashInCode);
console.log(`Wallet ID: ${walletId}`);

// 2. Create transaction with allowance
const transaction = await api.createTransaction({
payments: [{
description: 'Cash deposit',
price: amount * 100,
currency: 'EUR'
}],
allowance: {
id: allowanceId,
optional: true
}
});

console.log(`Transaction created: ${transaction.transaction_key}`);

// 3. Reserve with wallet ID
const reserved = await api.reserveTransaction(
transaction.transaction_key,
walletId
);

if (reserved.status !== 'reserved') {
throw new Error('Failed to reserve transaction');
}

console.log('Transaction reserved');

// 4. Confirm transaction
const confirmed = await api.confirmTransaction(
transaction.transaction_key
);

if (confirmed.status !== 'confirmed') {
throw new Error('Failed to confirm transaction');
}

console.log('✅ Cash deposited successfully');

return confirmed;
}

// Usage
const code = scanCashInCode();
await processCashIn(code, 50.00, 784);

Advanced Topics

Error Handling

Invalid Cash-in Code

{
"error": "invalid_request",
"error_description": "Invalid cash-in code format"
}

Solution: Verify code format starts with "EVP".

Wallet Not Found

{
"error": "not_found",
"error_description": "Wallet not found"
}

Solution: Ask customer to generate new code.

Allowance Limit Exceeded

{
"error": "allowance_limit_exceeded",
"error_description": "Amount exceeds allowance limit"
}

Solution: Reduce amount or split into multiple deposits.

Best Practices

1. Validate Cash-in Code

function validateCashInCode(code) {
if (!code.startsWith('EVP')) {
throw new Error('Invalid code format');
}

if (code.length !== 15) {
throw new Error('Invalid code length');
}

const walletId = extractWalletId(code);
if (walletId <= 0) {
throw new Error('Invalid wallet ID');
}

return true;
}

2. Verify Cash Amount

function verifyCashAmount(receivedCash, transactionAmount) {
if (receivedCash !== transactionAmount) {
throw new Error('Cash amount mismatch');
}
return true;
}

3. Set Deposit Limits

const DEPOSIT_LIMITS = {
min: 5.00,
max: 1000.00,
daily: 5000.00
};

function checkDepositLimit(amount) {
if (amount < DEPOSIT_LIMITS.min) {
throw new Error(`Minimum deposit: €${DEPOSIT_LIMITS.min}`);
}
if (amount > DEPOSIT_LIMITS.max) {
throw new Error(`Maximum deposit: €${DEPOSIT_LIMITS.max}`);
}
}
Security Considerations

Do:

  • ✅ Verify customer identity for large deposits
  • ✅ Count cash accurately before processing
  • ✅ Log all transactions for audit trail
  • ✅ Implement daily deposit limits per customer
  • ✅ Use secure cash handling procedures
  • ✅ Verify code hasn't been used previously

Don't:

  • ❌ Don't accept cash without valid code
  • ❌ Don't process deposits without cash verification
Cash Handling Procedure

1. Receive Cash

  • Count cash in front of customer
  • Verify denominations
  • Check for counterfeit bills

2. Scan Code

  • Ask customer to show cash-in code
  • Scan with barcode reader
  • Verify code format

3. Process Transaction

  • Create and confirm transaction
  • Wait for confirmation

4. Provide Receipt

  • Print transaction receipt
  • Include transaction ID, wallet ID, timestamp

Receipt Template:

================================
PAYSERA CASH DEPOSIT
================================

Transaction ID: 2988
Wallet ID: 14471
Date: 2025-10-31 11:00:00

Amount Deposited: €50.00
Fee: €0.00
--------------------------------
Total: €50.00

Status: CONFIRMED

Thank you!
================================