Skip to main content

Transactions API

The Transactions API enables you to process payments, track purchases, manage refunds, and analyze revenue across your games. Support both real-money transactions and virtual currency exchanges with comprehensive financial analytics and reporting.

Authentication

Most endpoints require authentication using either:

  • API Key: Include x-api-key header
  • Cognito JWT: Include Authorization: Bearer <token> header
  • Developer Auth: Special authentication for developer operations
  • Admin Auth: Required for refund operations

The payment webhook endpoint (processPaymentWebhook) is public for integration with payment providers.

Base URL

https://sdk.getjar.com/transactions

Core Concepts

Transaction Types

TypeDescription
PURCHASEReal-money purchase of products
REFUNDRefund of a previous purchase
EARNEDCurrency earned through gameplay/rewards
SPENTVirtual currency spent on in-game items
VIRTUAL_PURCHASEPurchase using virtual currency

Transaction Status Flow

PENDING → PROCESSING → COMPLETED
↓ ↓
FAILED CANCELLED

COMPLETED → REFUNDED (after refund)

Currency Support

  • Real Money: USD, EUR, GBP, and other standard currency codes
  • Virtual: In-game currencies (gold, gems, credits, etc.)

Payment Methods

  • CREDIT_CARD: Credit/debit card payments
  • PAYPAL: PayPal payments
  • STRIPE: Stripe payment processing
  • APPLE_PAY: Apple Pay payments
  • GOOGLE_PAY: Google Pay payments
  • VIRTUAL_CURRENCY: Virtual currency transactions

Create Transaction

Initialize a new transaction for purchases, virtual currency exchanges, or user rewards. Virtual currency transactions are auto-completed.

Endpoint

POST /transactions

Request Body

{
userId: string; // Required: User identifier
appId: string; // Required: Application identifier
productId?: string; // Product identifier (for purchases)
amount: number; // Required: Transaction amount
currency: string; // Required: USD, EUR, GBP, VIRTUAL
type: string; // Required: PURCHASE, REFUND, EARNED, SPENT, VIRTUAL_PURCHASE
paymentMethod?: string; // CREDIT_CARD, PAYPAL, STRIPE, APPLE_PAY, GOOGLE_PAY, VIRTUAL_CURRENCY
description?: string; // Transaction description
metadata?: object; // Additional metadata
virtualCurrency?: { // For virtual currency transactions
currencyType: string; // Currency type (e.g., 'gold', 'gems')
balanceBefore: number; // Balance before transaction
balanceAfter: number; // Balance after transaction
};
}

Response

{
transactionId: string;
userId: string;
appId: string;
productId: string | null;
amount: number;
currency: string;
type: string;
status: string; // PENDING or COMPLETED (for virtual)
paymentMethod: string | null;
virtualCurrency: {
currencyType: string;
balanceBefore: number;
balanceAfter: number;
} | null;
createdAt: string;
}

Example: Real Money Purchase

import { TransactionsApi } from "@getjar-iap/sdk";

const transactionsApi = new TransactionsApi(configuration);

const transaction = await transactionsApi.createTransaction({
body: {
appId: "app_123",
userId: "user_123",
productId: "prod_123",
amount: 9.99,
currency: "USD",
type: "PURCHASE",
paymentMethod: "STRIPE",
description: "Gold Pack 100",
metadata: {
platform: "IOS",
appVersion: "1.2.3",
},
},
});

console.log("Transaction ID:", transaction.data.transactionId);
console.log("Status:", transaction.data.status); // PENDING

Example: Virtual Currency Transaction

const virtualTransaction = await transactionsApi.createTransaction({
body: {
appId: "app_123",
userId: "user_123",
amount: 100,
currency: "VIRTUAL",
type: "VIRTUAL_PURCHASE",
paymentMethod: "VIRTUAL_CURRENCY",
description: "Health Potion",
virtualCurrency: {
currencyType: "gold",
balanceBefore: 500,
balanceAfter: 400,
},
},
});

console.log("Status:", virtualTransaction.data.status); // COMPLETED (auto-completed)
console.log(
"New Balance:",
virtualTransaction.data.virtualCurrency?.balanceAfter
);

Example: Earned Currency

const reward = await transactionsApi.createTransaction({
body: {
appId: "app_123",
userId: "user_123",
amount: 50,
currency: "VIRTUAL",
type: "EARNED",
description: "Daily login bonus",
virtualCurrency: {
currencyType: "gold",
balanceBefore: 400,
balanceAfter: 450,
},
},
});

console.log("Earned:", reward.data.amount, "gold");

Response Codes

CodeDescription
201Transaction created successfully
400Insufficient balance or invalid data
401Unauthorized
404User or product does not exist

Complete Transaction

Mark a transaction as completed after successful payment processing. Updates user virtual currency balance if applicable.

Endpoint

PUT /transactions/:transactionId/complete

Parameters

ParameterTypeRequiredDescription
transactionIdstringYesThe unique transaction identifier

Request Body

{
externalTransactionId?: string; // Payment provider transaction ID
receiptId?: string; // Receipt identifier
metadata?: object; // Additional metadata
}

Response

{
transactionId: string;
status: string; // COMPLETED
externalTransactionId: string;
updatedAt: string;
}

Example

const completed = await transactionsApi.completeTransaction({
transactionId: "txn_1234567890_abc123",
body: {
externalTransactionId: "stripe_ch_1234567890",
receiptId: "receipt_abc123",
metadata: {
completedAt: new Date().toISOString(),
ipAddress: "192.168.1.1",
},
},
});

console.log("Transaction completed:", completed.data.transactionId);
console.log("Status:", completed.data.status);

Response Codes

CodeDescription
200Transaction completed successfully
400Transaction cannot be completed (not PENDING/PROCESSING)
401Unauthorized
404Transaction does not exist

Fail Transaction

Mark a transaction as failed with a reason. Used when payment processing fails.

Endpoint

PUT /transactions/:transactionId/fail

Parameters

ParameterTypeRequiredDescription
transactionIdstringYesThe unique transaction identifier

Request Body

{
failureReason: string; // Required: Reason for failure
}

Response

{
transactionId: string;
status: string; // FAILED
failureReason: string;
updatedAt: string;
}

Example

const failed = await transactionsApi.failTransaction({
transactionId: "txn_1234567890_abc123",
body: {
failureReason: "Insufficient funds",
},
});

console.log("Transaction failed:", failed.data.failureReason);

Response Codes

CodeDescription
200Transaction marked as failed
400Transaction cannot be failed (not PENDING/PROCESSING)
401Unauthorized
404Transaction does not exist

Process Refund

Create a refund transaction for a completed purchase. Original transaction will be marked as REFUNDED.

Endpoint

POST /transactions/:transactionId/refund

Parameters

ParameterTypeRequiredDescription
transactionIdstringYesThe original transaction identifier

Request Body

{
refundAmount: number; // Required: Amount to refund
refundReason?: string; // Reason for refund
metadata?: object; // Additional metadata
}

Response

{
transactionId: string; // New refund transaction ID
userId: string;
amount: number;
type: string; // REFUND
status: string; // COMPLETED
metadata: {
originalTransactionId: string;
refundReason: string;
}
}

Example

const refund = await transactionsApi.refundTransaction({
transactionId: "txn_1234567890_abc123",
body: {
refundAmount: 9.99,
refundReason: "Customer request",
metadata: {
requestedBy: "support_agent_42",
ticketId: "TICKET-12345",
},
},
});

console.log("Refund transaction:", refund.data.transactionId);
console.log("Original:", refund.data.metadata?.originalTransactionId);

Response Codes

CodeDescription
201Refund processed successfully
400Only completed transactions can be refunded
401Unauthorized
404Transaction does not exist

Get Transaction by ID

Retrieve detailed information about a specific transaction including related user, app, and product details.

Endpoint

GET /transactions/:transactionId

Parameters

ParameterTypeRequiredDescription
transactionIdstringYesThe unique transaction identifier

Response

{
transactionId: string;
userId: string;
appId: string;
productId: string | null;
userProductId: string | null;
amount: number;
currency: string;
type: string;
status: string;
paymentMethod: string | null;
externalTransactionId: string | null;
receiptId: string | null;
description: string | null;
failureReason: string | null;
virtualCurrency: {
currencyType: string;
balanceBefore: number;
balanceAfter: number;
} | null;
metadata: object;
createdAt: string;
updatedAt: string;
user: object | null;
app: object | null;
product: object | null;
}

Example

const transaction = await transactionsApi.getTransactionById({
transactionId: "txn_1234567890_abc123",
});

console.log("Amount:", `$${transaction.data.amount}`);
console.log("Status:", transaction.data.status);
console.log("Payment Method:", transaction.data.paymentMethod);
console.log("User:", transaction.data.user);
console.log("Product:", transaction.data.product);

Response Codes

CodeDescription
200Transaction retrieved
401Unauthorized
404Transaction does not exist

Get User Transactions

Retrieve a paginated list of transactions for a specific user with optional filters by status, type, and date range.

Endpoint

GET /transactions/user/:userId

Parameters

ParameterTypeRequiredDescription
userIdstringYesThe unique user identifier
pagenumberNoPage number (default: 1)
limitnumberNoItems per page (default: 20)
statusstringNoFilter by status
typestringNoFilter by type
startDatestringNoStart date (ISO format)
endDatestringNoEnd date (ISO format)

Response

{
items: Array<{
transactionId: string;
userId: string;
appId: string;
amount: number;
currency: string;
type: string;
status: string;
paymentMethod: string;
description: string;
createdAt: string;
}>;
pagination: {
total: number;
page: number;
limit: number;
totalPages: number;
hasNextPage: boolean;
hasPreviousPage: boolean;
}
}

Example

// Get all user transactions
const transactions = await transactionsApi.getUserTransactions({
userId: "user_123",
page: 1,
limit: 20,
});

console.log("Total transactions:", transactions.data.pagination.total);

// Get completed purchases only
const purchases = await transactionsApi.getUserTransactions({
userId: "user_123",
status: "COMPLETED",
type: "PURCHASE",
page: 1,
limit: 50,
});

console.log("Completed purchases:", purchases.data.items);

// Get transactions for date range
const monthlyTransactions = await transactionsApi.getUserTransactions({
userId: "user_123",
startDate: "2025-10-01T00:00:00Z",
endDate: "2025-10-31T23:59:59Z",
page: 1,
limit: 100,
});

console.log("October transactions:", monthlyTransactions.data.items.length);

Response Codes

CodeDescription
200Transactions retrieved
401Unauthorized
404User does not exist

Get User Spending Summary

Retrieve comprehensive spending and earning analytics for a user with breakdowns by type and currency.

Endpoint

GET /transactions/user/:userId/summary

Parameters

ParameterTypeRequiredDescription
userIdstringYesThe unique user identifier
startDatestringNoStart date (ISO format)
endDatestringNoEnd date (ISO format)

Response

{
totalSpent: number;
totalEarned: number;
netBalance: number; // earned - spent
transactionCount: number;
byType: {
PURCHASE: number;
EARNED: number;
SPENT: number;
VIRTUAL_PURCHASE: number;
}
byCurrency: {
USD: number;
EUR: number;
VIRTUAL: number;
}
byStatus: {
COMPLETED: number;
PENDING: number;
REFUNDED: number;
}
averageTransactionAmount: number;
largestTransaction: {
transactionId: string;
amount: number;
createdAt: string;
}
}

Example

const summary = await transactionsApi.getUserSpendingSummary({
userId: "user_123",
});

console.log("💰 User Spending Summary:");
console.log("Total Spent:", `$${summary.data.totalSpent.toFixed(2)}`);
console.log("Total Earned:", `$${summary.data.totalEarned.toFixed(2)}`);
console.log("Net Balance:", `$${summary.data.netBalance.toFixed(2)}`);
console.log("Transactions:", summary.data.transactionCount);
console.log("Average:", `$${summary.data.averageTransactionAmount.toFixed(2)}`);

console.log("\n📊 By Type:");
Object.entries(summary.data.byType).forEach(([type, amount]) => {
console.log(`${type}: $${amount.toFixed(2)}`);
});

console.log("\n💵 By Currency:");
Object.entries(summary.data.byCurrency).forEach(([currency, amount]) => {
console.log(`${currency}: $${amount.toFixed(2)}`);
});

// Get summary for specific period
const monthlySummary = await transactionsApi.getUserSpendingSummary({
userId: "user_123",
startDate: "2025-10-01T00:00:00Z",
endDate: "2025-10-31T23:59:59Z",
});

console.log(
"\nOctober Spending:",
`$${monthlySummary.data.totalSpent.toFixed(2)}`
);

Response Codes

CodeDescription
200Summary retrieved
401Unauthorized
404User does not exist

Get App Transactions

Retrieve a paginated list of all transactions for a specific app with optional filters.

Endpoint

GET /transactions/app/:appId

Parameters

ParameterTypeRequiredDescription
appIdstringYesThe application identifier
pagenumberNoPage number (default: 1)
limitnumberNoItems per page (default: 20)
statusstringNoFilter by status
typestringNoFilter by type
startDatestringNoStart date (ISO format)
endDatestringNoEnd date (ISO format)

Example

const appTransactions = await transactionsApi.getAppTransactions({
appId: "app_123",
page: 1,
limit: 100,
});

console.log("Total transactions:", appTransactions.data.pagination.total);
console.log("Total revenue:", calculateRevenue(appTransactions.data.items));

Response Codes

CodeDescription
200Transactions retrieved
401Unauthorized
403Forbidden
404App does not exist

Get App Revenue Statistics

Retrieve comprehensive revenue analytics for an app including total revenue, transaction counts, and breakdowns.

Endpoint

GET /transactions/app/:appId/stats

Parameters

ParameterTypeRequiredDescription
appIdstringYesThe application identifier
startDatestringNoStart date (ISO format)
endDatestringNoEnd date (ISO format)

Response

{
totalRevenue: number;
totalTransactions: number;
completedTransactions: number;
pendingTransactions: number;
failedTransactions: number;
refundedTransactions: number;
totalRefunds: number;
netRevenue: number; // revenue - refunds
averageTransactionValue: number;
byType: {
PURCHASE: number;
VIRTUAL_PURCHASE: number;
}
byCurrency: {
USD: number;
EUR: number;
GBP: number;
}
byPaymentMethod: {
STRIPE: number;
APPLE_PAY: number;
GOOGLE_PAY: number;
PAYPAL: number;
}
topProducts: Array<{
productId: string;
productName: string;
revenue: number;
salesCount: number;
}>;
revenueOverTime: Array<{
date: string; // YYYY-MM-DD
revenue: number;
transactionCount: number;
}>;
}

Example

const stats = await transactionsApi.getAppRevenueStats({
appId: "app_123",
});

console.log("📈 Revenue Statistics:");
console.log("Total Revenue:", `$${stats.data.totalRevenue.toLocaleString()}`);
console.log("Net Revenue:", `$${stats.data.netRevenue.toLocaleString()}`);
console.log("Total Transactions:", stats.data.totalTransactions);
console.log(
"Average Transaction:",
`$${stats.data.averageTransactionValue.toFixed(2)}`
);
console.log("Completed:", stats.data.completedTransactions);
console.log("Refunded:", stats.data.refundedTransactions);

console.log("\n💳 By Payment Method:");
Object.entries(stats.data.byPaymentMethod).forEach(([method, count]) => {
console.log(`${method}: ${count} transactions`);
});

console.log("\n🏆 Top Products:");
stats.data.topProducts.slice(0, 5).forEach((product, index) => {
console.log(
`${index + 1}. ${
product.productName
}: $${product.revenue.toLocaleString()} (${product.salesCount} sales)`
);
});

// Get monthly stats
const monthlyStats = await transactionsApi.getAppRevenueStats({
appId: "app_123",
startDate: "2025-10-01T00:00:00Z",
endDate: "2025-10-31T23:59:59Z",
});

console.log(
"\nOctober Revenue:",
`$${monthlyStats.data.totalRevenue.toFixed(2)}`
);

Response Codes

CodeDescription
200Statistics retrieved
401Unauthorized
404App does not exist

Process Payment Webhook

Endpoint for payment provider webhooks (Stripe, PayPal, etc.). Updates transaction status based on payment provider events. This endpoint is public.

Endpoint

POST /transactions/webhook/payment

Request Body

{
transactionId: string; // Required: Transaction identifier
externalTransactionId: string; // Required: Provider transaction ID
status: string; // Required: 'success' or 'failed'
receiptData?: string; // Optional receipt data
metadata?: object; // Additional metadata
}

Response

{
transactionId: string;
status: string; // COMPLETED or FAILED
message: string;
}

Example: Stripe Webhook Handler

// Server-side webhook handler
app.post("/stripe/webhook", async (req, res) => {
const signature = req.headers["stripe-signature"];
const event = stripe.webhooks.constructEvent(
req.body,
signature,
webhookSecret
);

if (event.type === "charge.succeeded") {
const charge = event.data.object;

await transactionsApi.processPaymentWebhook({
body: {
transactionId: charge.metadata.transactionId,
externalTransactionId: charge.id,
status: "success",
receiptData: JSON.stringify(charge),
},
});
}

res.json({ received: true });
});

Response Codes

CodeDescription
200Webhook processed successfully
404Transaction not found

Complete Example

Here's a complete workflow for processing transactions:

import { Configuration, TransactionsApi } from "@getjar-iap/sdk";

const configuration = new Configuration({
basePath: "https://sdk.getjar.com",
apiKey: "your-api-key",
});

const transactionsApi = new TransactionsApi(configuration);

async function processPayment() {
const appId = "app_123";
const userId = "user_123";
const productId = "prod_123";

console.log("💳 Processing payment...\n");

try {
// 1. Create transaction
const transaction = await transactionsApi.createTransaction({
body: {
appId,
userId,
productId,
amount: 9.99,
currency: "USD",
type: "PURCHASE",
paymentMethod: "STRIPE",
description: "Gold Pack 100",
metadata: {
platform: "IOS",
appVersion: "1.2.3",
},
},
});

console.log("✓ Transaction created:", transaction.data.transactionId);
console.log("Status:", transaction.data.status);

const transactionId = transaction.data.transactionId;

// 2. Process payment with Stripe (example)
// const stripeCharge = await stripe.charges.create({...});

// 3. Complete transaction after successful payment
const completed = await transactionsApi.completeTransaction({
transactionId,
body: {
externalTransactionId: "stripe_ch_1234567890",
receiptId: "receipt_abc123",
metadata: {
completedAt: new Date().toISOString(),
},
},
});

console.log("\n✓ Transaction completed");
console.log("External ID:", completed.data.externalTransactionId);

// 4. Get transaction details
const details = await transactionsApi.getTransactionById({
transactionId,
});

console.log("\n📄 Transaction Details:");
console.log("Amount:", `$${details.data.amount}`);
console.log("Type:", details.data.type);
console.log("Status:", details.data.status);
console.log("Method:", details.data.paymentMethod);

// 5. Get user summary
const summary = await transactionsApi.getUserSpendingSummary({
userId,
});

console.log("\n💰 User Summary:");
console.log("Total Spent:", `$${summary.data.totalSpent.toFixed(2)}`);
console.log("Total Transactions:", summary.data.transactionCount);

return transaction;
} catch (error: any) {
console.error("\n❌ Payment failed:", error.response?.data?.message);

// Mark transaction as failed
if (error.response?.data?.transactionId) {
await transactionsApi.failTransaction({
transactionId: error.response.data.transactionId,
body: {
failureReason: error.message || "Payment processing failed",
},
});
}

throw error;
}
}

// Run the payment flow
processPayment()
.then(() => console.log("\n✅ Payment processed successfully!"))
.catch((error) => console.error("\n❌ Error:", error));

Virtual Currency Example

Complete example for virtual currency transactions:

async function virtualCurrencySystem(userId: string, appId: string) {
// User's current balance
let goldBalance = 500;

// 1. User earns gold from daily login
const dailyReward = await transactionsApi.createTransaction({
body: {
appId,
userId,
amount: 50,
currency: "VIRTUAL",
type: "EARNED",
description: "Daily login bonus",
virtualCurrency: {
currencyType: "gold",
balanceBefore: goldBalance,
balanceAfter: goldBalance + 50,
},
},
});

goldBalance += 50;
console.log("✓ Earned 50 gold. New balance:", goldBalance);

// 2. User purchases item with gold
const purchase = await transactionsApi.createTransaction({
body: {
appId,
userId,
amount: 100,
currency: "VIRTUAL",
type: "SPENT",
description: "Health Potion",
virtualCurrency: {
currencyType: "gold",
balanceBefore: goldBalance,
balanceAfter: goldBalance - 100,
},
},
});

goldBalance -= 100;
console.log("✓ Spent 100 gold. New balance:", goldBalance);

// 3. Get user's virtual currency history
const transactions = await transactionsApi.getUserTransactions({
userId,
type: "EARNED",
limit: 10,
});

console.log("\n💎 Recent Earnings:");
transactions.data.items.forEach((txn) => {
console.log(
`${txn.description}: +${txn.amount} ${txn.virtualCurrency?.currencyType}`
);
});

return { goldBalance, transactions };
}

Revenue Analytics Dashboard

Build a comprehensive revenue dashboard:

async function buildRevenueDashboard(appId: string) {
// Get current month stats
const now = new Date();
const monthStart = new Date(now.getFullYear(), now.getMonth(), 1);

const stats = await transactionsApi.getAppRevenueStats({
appId,
startDate: monthStart.toISOString(),
endDate: now.toISOString(),
});

// Calculate key metrics
const conversionRate =
(stats.data.completedTransactions / stats.data.totalTransactions) * 100;
const refundRate =
(stats.data.refundedTransactions / stats.data.completedTransactions) * 100;

const dashboard = {
overview: {
totalRevenue: `$${stats.data.totalRevenue.toLocaleString()}`,
netRevenue: `$${stats.data.netRevenue.toLocaleString()}`,
transactions: stats.data.totalTransactions,
avgTransaction: `$${stats.data.averageTransactionValue.toFixed(2)}`,
conversionRate: `${conversionRate.toFixed(1)}%`,
refundRate: `${refundRate.toFixed(1)}%`,
},
status: {
completed: stats.data.completedTransactions,
pending: stats.data.pendingTransactions,
failed: stats.data.failedTransactions,
refunded: stats.data.refundedTransactions,
},
paymentMethods: Object.entries(stats.data.byPaymentMethod).map(
([method, count]) => ({
method,
transactions: count,
percentage: ((count / stats.data.totalTransactions) * 100).toFixed(1),
})
),
topProducts: stats.data.topProducts.slice(0, 5),
timeline: stats.data.revenueOverTime.map((day) => ({
date: day.date,
revenue: `$${day.revenue.toFixed(2)}`,
transactions: day.transactionCount,
})),
};

console.log("📊 Revenue Dashboard\n");
console.log("Overview:");
console.log(JSON.stringify(dashboard.overview, null, 2));
console.log("\nTransaction Status:");
console.log(JSON.stringify(dashboard.status, null, 2));
console.log("\nPayment Methods:");
console.log(JSON.stringify(dashboard.paymentMethods, null, 2));
console.log("\nTop 5 Products:");
console.log(JSON.stringify(dashboard.topProducts, null, 2));

return dashboard;
}

Best Practices

Transaction Processing

  1. Always Handle Errors: Payment processing can fail

    try {
    const transaction = await createTransaction({...});
    // Process payment
    await completeTransaction({...});
    } catch (error) {
    await failTransaction({...});
    // Notify user
    }
  2. Idempotency: Use unique transaction IDs

    const transactionId = `txn_${Date.now()}_${userId}`;
  3. Metadata: Include useful context

    metadata: {
    platform: "IOS",
    appVersion: "1.2.3",
    deviceId: "device_abc123",
    ipAddress: "192.168.1.1"
    }
  4. Receipt Storage: Always store receipt IDs

    await completeTransaction({
    transactionId,
    body: {
    receiptId: providerReceiptId,
    externalTransactionId: providerTransactionId,
    },
    });

Virtual Currency

  1. Balance Tracking: Always track before/after balances

    virtualCurrency: {
    currencyType: "gold",
    balanceBefore: currentBalance,
    balanceAfter: currentBalance - amount
    }
  2. Validate Sufficient Balance: Check before creating transaction

    if (userBalance < purchaseAmount) {
    throw new Error("Insufficient balance");
    }
  3. Auto-Completion: Virtual currency transactions complete automatically

    const virtualTxn = await createTransaction({
    type: "VIRTUAL_PURCHASE",
    currency: "VIRTUAL",
    });
    // Already completed, no need to call completeTransaction

Refund Management

  1. Document Reasons: Always include refund reason

    await refundTransaction({
    transactionId,
    body: {
    refundAmount: originalAmount,
    refundReason: "Customer request - accidental purchase",
    metadata: {
    supportTicket: "TICKET-12345",
    },
    },
    });
  2. Partial Refunds: Support partial refund amounts

    refundAmount: originalAmount * 0.5; // 50% refund
  3. Track Refund Rates: Monitor for abuse

    const stats = await getAppRevenueStats({ appId });
    const refundRate =
    (stats.refundedTransactions / stats.completedTransactions) * 100;
    if (refundRate > 5) {
    // Investigate high refund rate
    }

Analytics & Reporting

  1. Regular Monitoring: Check revenue stats daily

    // Daily revenue check
    const today = new Date();
    const stats = await getAppRevenueStats({
    appId,
    startDate: today.toISOString(),
    endDate: new Date(today.getTime() + 24 * 60 * 60 * 1000).toISOString(),
    });
  2. Compare Periods: Month-over-month growth

    const thisMonth = await getAppRevenueStats({
    appId,
    startDate: thisMonthStart,
    endDate: now,
    });

    const lastMonth = await getAppRevenueStats({
    appId,
    startDate: lastMonthStart,
    endDate: lastMonthEnd,
    });

    const growth =
    ((thisMonth.totalRevenue - lastMonth.totalRevenue) /
    lastMonth.totalRevenue) *
    100;
  3. User Segmentation: Identify high-value users

    const summary = await getUserSpendingSummary({ userId });

    if (summary.totalSpent > 100) {
    // High-value user - offer VIP rewards
    }

Common Patterns

Payment Gateway Integration

async function stripePaymentFlow(
userId: string,
productId: string,
amount: number
) {
// 1. Create GetJar transaction
const transaction = await transactionsApi.createTransaction({
body: {
appId: "app_123",
userId,
productId,
amount,
currency: "USD",
type: "PURCHASE",
paymentMethod: "STRIPE",
},
});

try {
// 2. Process with Stripe
const paymentIntent = await stripe.paymentIntents.create({
amount: Math.round(amount * 100), // cents
currency: "usd",
metadata: {
transactionId: transaction.data.transactionId,
},
});

// 3. Complete on success
await transactionsApi.completeTransaction({
transactionId: transaction.data.transactionId,
body: {
externalTransactionId: paymentIntent.id,
receiptId: paymentIntent.receipt_email,
},
});

return { success: true, transaction };
} catch (error) {
// 4. Fail on error
await transactionsApi.failTransaction({
transactionId: transaction.data.transactionId,
body: {
failureReason: error.message,
},
});

throw error;
}
}

Subscription Billing

async function processSubscriptionPayment(
userId: string,
subscriptionId: string,
amount: number
) {
const transaction = await transactionsApi.createTransaction({
body: {
appId: "app_123",
userId,
productId: subscriptionId,
amount,
currency: "USD",
type: "PURCHASE",
paymentMethod: "STRIPE",
description: "Monthly subscription",
metadata: {
subscriptionId,
billingPeriod: new Date().toISOString(),
},
},
});

return transaction;
}

Transaction History Export

async function exportTransactionHistory(
userId: string,
startDate: string,
endDate: string
) {
const allTransactions = [];
let page = 1;
let hasMore = true;

while (hasMore) {
const result = await transactionsApi.getUserTransactions({
userId,
startDate,
endDate,
page,
limit: 100,
});

allTransactions.push(...result.data.items);
hasMore = result.data.pagination.hasNextPage;
page++;
}

// Convert to CSV or export format
const csv = allTransactions
.map(
(txn) =>
`${txn.transactionId},${txn.amount},${txn.currency},${txn.type},${txn.status},${txn.createdAt}`
)
.join("\n");

return csv;
}

Error Handling

async function safeTransactionOperation() {
try {
const transaction = await transactionsApi.createTransaction({
body: {
/* ... */
},
});

return {
success: true,
data: transaction.data,
};
} catch (error) {
if (error.response) {
switch (error.response.status) {
case 400:
if (error.response.data.message.includes("Insufficient balance")) {
console.error("User doesn't have enough virtual currency");
} else {
console.error("Invalid transaction data");
}
break;
case 401:
console.error("Authentication required");
break;
case 404:
console.error("User or product not found");
break;
default:
console.error("Unexpected error:", error.response.status);
}
}

return {
success: false,
error: error.message,
};
}
}

Support

For additional help or questions: