Skip to main content

Allowance Resource

The Allowance Resource enables automatic recurring payments without user interaction for each charge. Once a user approves an allowance, you can charge their wallet automatically as long as the payment stays within the predefined limits.

Quick Start

Perfect for subscriptions, recurring billing, and automated charges. See Payment Concepts for basics.

Allowance Object

Structure

{
"id": 12345,
"transaction_key": "pDAlAZ3z",
"created_at": 1698675600,
"confirmed_at": 1698675680,
"valid": {
"from": 1698675680,
"until": 1701267680
},
"description": "Premium Subscription",
"max_price": 999,
"currency": "EUR",
"limits": [
{
"max_price": 999,
"period": 2592000 // 30 days
}
]
}
View Fields Reference
FieldTypeDescription
idintegerAllowance ID (unique)
transaction_keystringTransaction that created allowance
created_attimestampWhen allowance was created
confirmed_attimestampWhen user confirmed allowance
canceled_attimestampWhen allowance was canceled (if canceled)
validobjectValidity period
valid.fromtimestampValid from this time
valid.untiltimestampValid until this time
descriptionstringRequired. Allowance description
max_priceintegerRequired. Maximum price in cents (total)
currencystringRequired. Currency code (e.g., "EUR")
limitsarrayTime-based limits (optional)
optionalbooleanWhether allowance is optional

Creating an Allowance

View Creation Examples

Basic Allowance

POST /rest/v1/transaction

{
"allowance": {
"description": "Premium Subscription - Monthly",
"max_price": 999,
"currency": "EUR",
"valid": {
"for": 31536000 // 1 year in seconds
}
}
}

User flow:

  1. Redirect user to confirmation
  2. User approves allowance
  3. User returns to your site
  4. Confirm transaction
  5. Allowance is now active

Allowance with Payment

Create allowance together with first payment:

{
"payments": [{
"description": "First month - Premium",
"price": 999,
"currency": "EUR"
}],
"allowance": {
"description": "Premium Subscription",
"max_price": 999,
"currency": "EUR",
"valid": {
"for": 31536000 // 1 year
}
}
}

User approves both payment and allowance in one action.


Allowance Limits

View Limit Types

Total Limit Only

Simple total limit:

{
"description": "Service Credits",
"max_price": 10000, // 100 EUR total
"currency": "EUR",
"valid": {
"for": 7776000 // 90 days
}
}

Usage: 100 EUR total over 90 days, any distribution.

Time-Based Limits

Add recurring limits:

{
"description": "Monthly Subscription",
"max_price": 11988, // 119.88 EUR total (12 months)
"currency": "EUR",
"valid": {
"for": 31536000 // 1 year
},
"limits": [
{
"max_price": 999, // 9.99 EUR
"period": 2592000 // per 30 days
}
]
}

Usage: Max 9.99 EUR per month, 119.88 EUR total per year.

Multiple Time Limits

Stack different period limits:

{
"description": "Flexible Billing",
"max_price": 50000, // 500 EUR total
"currency": "EUR",
"limits": [
{
"max_price": 5000, // 50 EUR
"period": 86400 // per day
},
{
"max_price": 20000, // 200 EUR
"period": 604800 // per week
}
]
}

Usage: Max 50 EUR/day AND 200 EUR/week AND 500 EUR total.


Using an Allowance

Once user has approved an allowance, use it for automatic payments.

// 1. Create transaction with allowance
const tx = await createTransaction({
payments: [{
description: 'Monthly Subscription - Premium',
price: 999
}],
allowance_id: userAllowanceId
});

// 2. Reserve using allowance (automatic acceptance)
await reserveWithAllowance(tx.transaction_key, userWalletId);

// 3. Confirm
await confirmTransaction(tx.transaction_key);

// Done! No user interaction needed.

Allowance Lifecycle

States

Created → Accepted → Active → Expired/Canceled
StateDescriptionCan Use?
CreatedJust created, not yet confirmed❌ No
AcceptedUser confirmed, not yet active❌ No
ActiveConfirmed and within validity period✅ Yes
ExpiredValidity period ended❌ No
CanceledManually canceled❌ No

Allowance Rules

One Active Allowance Per Wallet/Client

  • ❌ Cannot have: Multiple active allowances from same client for same wallet
  • ✅ Can have: Allowances from different clients
  • ✅ Can have: Allowances for different wallets

New Allowance Cancels Previous

When user confirms new allowance, previous allowance (if exists) is canceled.

Validity Period

  • Starts: When user confirms allowance
  • Ends: valid.until timestamp
  • Cannot extend once set
  • Must create new to continue

Advanced Topics

Limit Checking

How Limits Are Checked

Before allowing payment with allowance:

  1. ✅ Total limit: Sum of all charges ≤ max_price
  2. ✅ Period limits: For each limit, sum within period ≤ limit.max_price
  3. ✅ Validity: Current time is within valid.from and valid.until
  4. ✅ Balance: Wallet has sufficient balance

Limit Calculation Example

Allowance:

  • Max 100 EUR total
  • Max 30 EUR per week

Usage:

  • Week 1: 25 EUR (✅ OK - within weekly limit)
  • Week 1: 10 EUR (❌ FAIL - exceeds weekly 30 EUR)
  • Week 2: 30 EUR (✅ OK - new week starts)
  • Week 3: 30 EUR (✅ OK)
  • Week 4: 20 EUR (❌ FAIL - exceeds total 100 EUR)

Handling Limit Exceeded

{
"error": "invalid_allowance",
"error_description": "Allowance limit would be exceeded by this payment"
}

Solutions: Reduce payment amount, Wait for next period, Request new allowance

Common Patterns

Pattern 1: Monthly Subscription

// Setup (once)
const setupAllowance = async () => {
const tx = await createTransaction({
allowance: {
description: 'Premium Subscription - Monthly',
max_price: 11988, // 12 months × 9.99
currency: 'EUR',
valid: { for: 31536000 }, // 1 year
limits: [
{
max_price: 999, // 9.99 per month
period: 2592000 // 30 days
}
]
},
redirect_uri: 'https://myapp.com/subscription-setup'
});

return tx.transaction_key;
};

// Monthly charge (automatic)
const chargeMonthly = async (allowanceId, walletId) => {
const tx = await createTransaction({
payments: [{
description: `Premium - ${currentMonth}`,
price: 999
}],
allowance_id: allowanceId
});

await reserveWithAllowance(tx.transaction_key, walletId);
await confirmTransaction(tx.transaction_key);
};

Pattern 2: Usage-Based Billing

// Charge for usage (as needed)
const chargeForUsage = async (amount) => {
const tx = await createTransaction({
payments: [{
description: `API Usage: ${apiCallCount} calls`,
price: amount
}],
allowance_id: userAllowanceId
});

await reserveWithAllowance(tx.transaction_key, walletId);
await confirmTransaction(tx.transaction_key);
};

Pattern 3: Subscription with Trial

// Month 1: Trial with allowance setup
const setupTrial = async () => {
const tx = await createTransaction({
payments: [{
description: 'Premium - Trial Month',
price: 99 // Discounted trial price
}],
allowance: {
description: 'Premium Subscription',
max_price: 11988, // Full year
currency: 'EUR',
valid: { for: 31536000 },
limits: [{
max_price: 999, // Regular price
period: 2592000
}]
}
});

return tx;
};
Monitoring & Tracking

Track Allowance Usage

Store in your database:

{
user_id: 12345,
allowance_id: 67890,
wallet_id: 14471,
created_at: '2024-01-01T00:00:00Z',
valid_until: '2025-01-01T00:00:00Z',
total_charged: 5994, // 59.94 EUR so far
total_limit: 11988, // 119.88 EUR total
last_charge: '2024-07-01T00:00:00Z',
charges_count: 6
}

Check Before Charging

const canCharge = (allowanceData, amount) => {
if (Date.now() > new Date(allowanceData.valid_until)) {
return { ok: false, reason: 'expired' };
}

if (allowanceData.total_charged + amount > allowanceData.total_limit) {
return { ok: false, reason: 'total_limit' };
}

return { ok: true };
};

Handle Renewals

const renewAllowance = async (userId) => {
const oldAllowance = await getAllowance(userId);
const daysLeft = (oldAllowance.valid_until - Date.now()) / 86400000;

if (daysLeft < 7) {
const tx = await createTransaction({
allowance: {
description: 'Premium Subscription - Renewal',
max_price: 11988,
currency: 'EUR',
valid: { for: 31536000 }
}
});

await notifyUser(userId, 'subscription_renewal', tx.transaction_key);
}
};
Error Handling

Common Errors

Allowance Limit Exceeded

{
"error": "invalid_allowance",
"error_description": "Payment would exceed allowance limit"
}

Solution: Wait for next period or create new allowance

Allowance Expired

{
"error": "invalid_allowance",
"error_description": "Allowance has expired"
}

Solution: Create new allowance

No Active Allowance

{
"error": "invalid_allowance",
"error_description": "User has no active allowance for this client"
}

Solution: User needs to create/approve allowance first

Insufficient Balance

{
"error": "insufficient_funds",
"error_description": "Wallet balance insufficient"
}

Solution: User needs to add funds (allowance doesn't guarantee balance)


Security Considerations

User Control

  • Users can view all active allowances
  • Users can cancel allowances anytime
  • Users receive notifications when charged
  • Users see transaction history

Your Responsibilities

  • Store allowance IDs securely
  • Validate before charging
  • Notify users when charging
  • Handle errors gracefully
  • Respect limits
  • Don't abuse allowance privileges

API Reference

MethodEndpointDescription
POST/rest/v1/transactionCreate transaction with allowance
PUT/rest/v1/transaction/{key}/reserve/{wallet}Reserve using allowance
GET/rest/v1/transaction/{key}Get allowance details

Full API reference: Wallet API Endpoints


What's Next?

Learn more about related topics:

  1. Payment Resource - Understanding payments
  2. Transaction Resource - Transaction management
  3. Samples & Examples - See allowance in action

Need Help?

Quick Reference

Perfect for: Subscriptions, recurring billing, usage-based charges
Key benefit: No user interaction for each charge
Important: One active allowance per wallet/client
Remember: Allowance ≠ guaranteed balance