RevKeen Docs
Using RevKeen

Payments and Refunds

Process payments, issue refunds, and manage the transaction lifecycle

RevKeen processes payments through your connected payment gateway, handling tokenization, authorization, capture, and refunds. This guide covers the complete payment flow, refund processing, credit notes, and best practices.

Supported Payment Methods

  • Credit/Debit Cards -- Visa, Mastercard, American Express, Discover, and more
  • ACH Bank Transfer -- Direct bank debits for US customers (lower fees)
  • Saved Cards -- Securely stored payment methods for returning customers (email verification + CVV required)

Payment Flow

RevKeen uses tokenization to ensure card data never touches your servers:

  1. Tokenization -- Customer enters card in secure form; token generated client-side.
  2. Authorization -- RevKeen verifies the card can be charged for the requested amount.
  3. Capture -- Funds are captured and transferred (usually immediate).
  4. Confirmation -- Customer receives receipt, subscription/invoice updated.

Processing Payments via API

Create a One-Time Payment

const payment = await client.payments.create({
  customerId: 'cus_xxxxxxxx',
  amount: 9900, // $99.00 in cents
  currency: 'USD',
  paymentMethodToken: 'tok_xxxxxxxx',
  description: 'Consulting fee',
  metadata: {
    orderId: 'order_12345',
  },
});

if (payment.data.status === 'succeeded') {
  console.log('Payment successful!');
  console.log('Transaction ID:', payment.data.transactionId);
}
payment = client.payments.create(
    customer_id="cus_xxxxxxxx",
    amount=9900,
    currency="USD",
    payment_method_token="tok_xxxxxxxx",
    description="Consulting fee",
    metadata={
        "order_id": "order_12345"
    }
)

if payment.data.status == "succeeded":
    print("Payment successful!")
    print(f"Transaction ID: {payment.data.transaction_id}")

Pay an Invoice

// Pay an existing invoice with saved payment method
const result = await client.invoices.pay('inv_xxxxxxxx');

// Or specify a different payment method
const result = await client.invoices.pay('inv_xxxxxxxx', {
  paymentMethodId: 'pm_xxxxxxxx',
});

console.log('Invoice paid:', result.data.paidAt);

Transaction Statuses

StatusDescriptionFunds
pendingPayment initiated, awaiting processingHeld
succeededPayment completed successfullyCaptured
failedPayment declined or error occurredNone
requires_actionAdditional verification needed (3DS)Held
refundedFull amount returned to customerReturned
partially_refundedPartial amount returnedPartial
voidedReversed before settlementReleased

Handling Declines

When a payment fails, RevKeen provides detailed decline information:

CategoryCommon CodesRecommended Action
Insufficient Funds300, 301Ask customer to use different card or try later
Card Declined200, 204Card blocked by issuer -- request new card
Invalid Card303, 530Card number invalid -- re-enter card details
Expired Card202, 223Request updated card information
CVV Mismatch225Re-enter CVV -- potential fraud indicator
Limit Exceeded402, 521Card limit reached -- try smaller amount or different card
try {
  const payment = await client.payments.create({
    customerId: 'cus_xxxxxxxx',
    amount: 9900,
    currency: 'USD',
    paymentMethodToken: 'tok_xxxxxxxx',
  });
} catch (error) {
  if (error.code === 'payment_declined') {
    console.log('Decline code:', error.declineCode);
    console.log('Message:', error.message);

    switch (error.declineCode) {
      case '300':
      case '301':
        return 'Insufficient funds. Please try a different card.';
      case '200':
        return 'Card declined. Please contact your bank.';
      default:
        return 'Payment failed. Please try again.';
    }
  }
}

3D Secure (3DS) Authentication

Some payments require additional verification through 3D Secure. RevKeen handles this automatically in the checkout flow:

  1. Payment initiated -- Gateway determines 3DS is required
  2. Customer redirected to bank's verification page
  3. Customer completes verification (password, SMS code, etc.)
  4. Customer redirected back -- Payment completes

3DS helps reduce fraud and shifts liability to the card issuer. It's required for Strong Customer Authentication (SCA) in the EU.

Reversing Payments: Void vs Refund

RevKeen provides intelligent payment reversal options based on settlement timing. Understanding when to use each method can save you significant processing fees.

How It Works

MethodTimingProcessing FeesCustomer Impact
VoidBefore daily settlement (typically before 8 PM ET)No feesCharge never appears on statement
RefundAfter daily settlementOriginal fees not returnedShows as separate refund transaction

Settlement Timing and Smart Warnings

RevKeen automatically tracks settlement timing for each payment gateway and provides real-time warnings to help you choose the best reversal method.

Safe to Void -- Settlement is 2+ hours away. Void will succeed with high confidence. This is the recommended option to avoid processing fees.

High-Risk Void Window -- Settlement is within 15 minutes. The batch may have already closed. If void fails, you will need to process a refund instead. The dashboard will show "Attempt Void" with a warning alert.

Settlement Complete -- Transaction has been settled. Void is no longer available. You must process a refund to return funds to the customer.

Smart Reversal Logic: RevKeen automatically determines eligibility based on your gateway's settlement schedule. When you view a payment, you'll see only the available options with clear warnings for high-risk scenarios.

Using the Dashboard

  1. Navigate to Invoice or Payment -- Go to Invoices, select invoice, click payment row actions menu.
  2. Choose Reversal Method -- The dialog will show available options based on settlement status. Review settlement timing information and any warnings displayed.
  3. Confirm and Execute -- Click the action button ("Void Payment", "Attempt Void", or "Process Refund") to execute the reversal.

Important: If a high-risk void fails because settlement already occurred, you will need to manually process a refund. The system cannot automatically fall back to refund due to accounting and tax implications.

Processing Refunds

// Full refund
const refund = await client.refunds.create({
  transactionId: 'txn_xxxxxxxx',
});

// Partial refund
const partialRefund = await client.refunds.create({
  transactionId: 'txn_xxxxxxxx',
  amount: 2500, // Refund $25.00
});

// Refund with reason
const refund = await client.refunds.create({
  transactionId: 'txn_xxxxxxxx',
  reason: 'Customer request',
});
# Full refund
refund = client.refunds.create(
    transaction_id="txn_xxxxxxxx"
)

# Partial refund
partial_refund = client.refunds.create(
    transaction_id="txn_xxxxxxxx",
    amount=2500
)

# Refund with reason
refund = client.refunds.create(
    transaction_id="txn_xxxxxxxx",
    reason="Customer request"
)

Refunds typically take 5-10 business days to appear on the customer's statement. You cannot refund more than the original transaction amount.

Credit Notes

Credit notes provide formal documentation for invoice adjustments, service credits, or refunds. They maintain a complete audit trail and handle complex scenarios like subscription cancellations and tax adjustments.

When to Use Credit Notes

  • Invoice Corrections -- Wrong amount charged, billing error, or service not delivered as promised.
  • Service Credits -- Goodwill credits, promotional adjustments, or compensation for service issues.
  • Subscription Cancellations -- Prorate refunds when canceling subscriptions mid-period.
  • Partial Refunds -- Return a portion of the invoice amount while keeping the invoice active.

Credit Note Options

Credit MethodEffectBest For
Refund to Payment MethodIssues credit note and automatically processes refund/voidCustomer paid and wants money back
Customer BalanceIssues credit note and adds credit to customer accountCustomer wants credit toward future purchases
Credit Note OnlyIssues credit note for record-keeping onlyManual refund outside RevKeen or goodwill gesture

Intelligent Tax Handling

RevKeen automatically calculates proportional tax adjustments when issuing credit notes:

  • Proportional Tax Credits -- Tax amounts are automatically calculated proportionally to the credited amount. For example, crediting 50% of an invoice also credits 50% of the tax.
  • Penny-Perfect Chain Handling -- When issuing multiple credit notes against the same invoice, the final credit note automatically "sweeps" any remaining fractional pennies of tax. This prevents 1-2 cent discrepancies that can occur with rounding in credit note chains.
  • Tax Provider Sync -- Credit notes automatically sync with your tax provider (Quaderno, TaxJar, etc.) to maintain accurate tax records and compliance reports.

Subscription Cancellation Protection

When issuing a credit note with subscription cancellation, RevKeen implements a safety guard: if you select "Refund to Payment Method" with subscription cancellation, the subscription will only cancel if the refund succeeds. This prevents scenarios where a customer loses access but didn't receive their refund due to gateway errors or expired payment methods.

If the refund fails, a warning is logged and the subscription remains active. You can then manually process the refund and cancel separately.

Creating Credit Notes

// Issue credit note with automatic refund
const creditNote = await client.creditNotes.create({
  invoiceId: 'inv_xxxxxxxx',
  amount: 5000, // $50.00 in cents
  reason: 'Service not delivered',
  creditMethod: 'refund_to_payment_method',
  cancelSubscription: true,
});

// Issue credit note with customer balance
const creditNote = await client.creditNotes.create({
  invoiceId: 'inv_xxxxxxxx',
  amount: 5000,
  reason: 'Goodwill credit',
  creditMethod: 'customer_balance',
});

// Credit note only (no financial movement)
const creditNote = await client.creditNotes.create({
  invoiceId: 'inv_xxxxxxxx',
  amount: 5000,
  reason: 'Manual adjustment',
  creditMethod: 'none',
});

Audit Trail: All credit notes include reason codes, creator information, timestamp, and links to associated refunds/voids. They appear on customer statements and integrate with your accounting system for complete financial reconciliation.

Payment Webhooks

Listen for payment events to keep your systems in sync:

EventTrigger
payment.succeededPayment completed successfully
payment.failedPayment was declined
payment.refundedRefund processed
payment.capturedAuthorized payment captured
payment.disputedChargeback received
payment.requires_actionAdditional customer action needed
void.succeededPre-settlement void completed
void.failedVoid failed (transaction already settled)
credit_note.createdCredit note issued against invoice
credit_note.voidedCredit note canceled or voided

Best Practices

  • Always Use Idempotency Keys -- Include an idempotency key with payment requests to prevent duplicate charges on retries.
  • Handle Webhooks -- Don't rely solely on API responses. Use webhooks for reliable payment status updates.
  • Store Transaction IDs -- Always store the transaction ID from successful payments for refunds and support inquiries.
  • Graceful Error Handling -- Show user-friendly error messages and provide clear next steps when payments fail.
  • Descriptive Statement Descriptors -- Use descriptive statement descriptors so customers recognize charges on their bank statements and reduce chargebacks.

On this page