Skip to content

Payment Management

Overview

Payment management handles post-processing operations including refunds, cancellations, disputes, retry logic, and transaction history. This guide covers the complete management lifecycle for payments after initial processing.

Table of Contents

Refunding Payments

Full Refund

Endpoint: POST /api/v1/sales/payments/{payment}/refund

Authentication: Required (Bearer token)

Purpose: Issue full or partial refund for completed payment

Prerequisites:

  • Payment must be in completed status
  • Payment must not be fully refunded already
  • Refund must be within allowed timeframe (typically 180 days)

Request Body (Full Refund):

json
{
  "amount": 347.47,
  "refund_reason": "product_return",
  "reason_details": "Customer returned product - defective",
  "notify_customer": true,
  "refund_method": "original_payment_method"
}

Response (200 OK):

json
{
  "message": "Payment refunded successfully",
  "data": {
    "id": 789,
    "payment_number": "PAY-12345678",
    "status": "refunded",
    "amount": 347.47,
    "refunded_amount": 347.47,
    "refund": {
      "id": 890,
      "refund_number": "REF-87654321",
      "amount": 347.47,
      "refund_reason": "product_return",
      "reason_details": "Customer returned product - defective",
      "refund_method": "credit_card",
      "processed_at": "2025-12-19T10:00:00Z",
      "expected_arrival": "2025-12-24"
    },
    "refunded_at": "2025-12-19T10:00:00Z",
    "customer_notified": true
  }
}

Partial Refund

Request Body:

json
{
  "amount": 100.00,
  "refund_reason": "partial_return",
  "reason_details": "Customer returned 1 of 2 items",
  "notify_customer": true
}

Response:

json
{
  "data": {
    "status": "partially_refunded",
    "amount": 347.47,
    "refunded_amount": 100.00,
    "remaining_amount": 247.47,
    "refund": {
      "id": 890,
      "amount": 100.00,
      "refund_reason": "partial_return"
    }
  }
}

Refund Reasons

Standard Refund Reasons:

  • customer_request - Customer requested refund
  • product_return - Product returned
  • defective_product - Product defective or damaged
  • wrong_item_shipped - Incorrect item shipped
  • duplicate_charge - Duplicate payment processed
  • cancelled_order - Order cancelled
  • service_not_provided - Service not delivered
  • billing_error - Billing mistake
  • other - Other reason (provide details)

Viewing Refunds

Endpoint: GET /api/v1/sales/payments/{payment}/refunds

Response (200 OK):

json
{
  "data": [
    {
      "id": 890,
      "refund_number": "REF-87654321",
      "amount": 100.00,
      "refund_reason": "partial_return",
      "refund_method": "credit_card",
      "status": "completed",
      "processed_at": "2025-12-19T10:00:00Z",
      "expected_arrival": "2025-12-24",
      "gateway_refund_id": "re_1234567890"
    }
  ],
  "meta": {
    "total_refunds": 1,
    "total_refunded": 100.00,
    "remaining_refundable": 247.47
  }
}

Canceling Payments

Cancel Payment

Endpoint: POST /api/v1/sales/payments/{payment}/cancel

Authentication: Required (Bearer token)

Purpose: Cancel payment before processing completes

Prerequisites:

  • Payment must be in pending or processing status
  • Payment not yet completed
  • Cancellation must be possible (not all gateways support mid-processing cancellation)

Request Body:

json
{
  "cancellation_reason": "Customer requested cancellation before processing",
  "notify_customer": true,
  "release_invoice_hold": true
}

Response (200 OK):

json
{
  "message": "Payment cancelled successfully",
  "data": {
    "id": 789,
    "payment_number": "PAY-12345678",
    "status": "cancelled",
    "cancelled_at": "2025-12-18T10:30:00Z",
    "cancellation_reason": "Customer requested cancellation before processing",
    "invoice_updated": true,
    "customer_notified": true
  }
}

What Happens on Cancellation:

  1. Payment status changes to cancelled
  2. No funds transferred
  3. Invoice remains unpaid
  4. Customer notified if requested
  5. Payment cannot be reactivated

Error Response:

json
{
  "error": "Cannot cancel payment",
  "message": "Payment already completed. Use refund endpoint instead.",
  "current_status": "completed"
}

Voiding Authorizations

Void Authorized Payment

Endpoint: POST /api/v1/sales/payments/{payment}/void

Authentication: Required (Bearer token)

Purpose: Cancel payment authorization and release reserved funds

Prerequisites:

  • Payment must be in authorized status
  • Authorization must not be expired
  • Authorization must not be captured

Request Body:

json
{
  "void_reason": "Order cancelled - void authorization",
  "notify_customer": true
}

Response (200 OK):

json
{
  "message": "Payment authorization voided successfully",
  "data": {
    "id": 789,
    "payment_number": "PAY-12345678",
    "status": "voided",
    "voided_at": "2025-12-18T15:00:00Z",
    "void_reason": "Order cancelled - void authorization",
    "authorization_released": true,
    "funds_available_to_customer": true,
    "customer_notified": true
  }
}

Void vs Cancel vs Refund:

  • Void: Release authorization (funds never captured)
  • Cancel: Stop pending/processing payment (before completion)
  • Refund: Return captured funds (after completion)

Retrying Failed Payments

Retry Failed Payment

Endpoint: POST /api/v1/sales/payments/{payment}/retry

Authentication: Required (Bearer token)

Purpose: Retry failed payment with same or updated details

Prerequisites:

  • Payment must be in failed status
  • Failure reason must be retryable (not fraud/blocked)
  • Updated payment details available (if failure due to invalid data)

Request Body (Retry with Same Details):

json
{
  "retry_reason": "Temporary gateway error - retrying",
  "use_original_details": true
}

Request Body (Retry with Updated Details):

json
{
  "retry_reason": "Updated card details provided by customer",
  "use_original_details": false,
  "payment_method_token": "pm_new_token_9876",
  "billing_address": {
    "street": "456 New St",
    "city": "San Francisco",
    "state": "CA",
    "postal_code": "94105",
    "country": "US"
  }
}

Response (200 OK):

json
{
  "message": "Payment retry initiated successfully",
  "data": {
    "id": 789,
    "payment_number": "PAY-12345678",
    "status": "processing",
    "retry_count": 1,
    "previous_failure_reason": "insufficient_funds",
    "retry_initiated_at": "2025-12-19T11:00:00Z"
  }
}

Automatic Retry Logic: The system can automatically retry failed payments based on configuration:

  • Retry 1: After 1 hour
  • Retry 2: After 24 hours
  • Retry 3: After 72 hours
  • Max retries: 3 (configurable)

Non-Retryable Failures:

  • Stolen card
  • Fraud detected
  • Invalid card number
  • Expired card (unless updated)
  • Customer blocked
  • Payment method disabled

Dispute Management

Handling Disputed Payments (Chargebacks)

Endpoint: POST /api/v1/sales/payments/{payment}/dispute

Authentication: Required (Bearer token)

Purpose: Record and manage payment disputes/chargebacks

Request Body:

json
{
  "dispute_reason": "fraudulent",
  "dispute_amount": 347.47,
  "dispute_date": "2025-12-25",
  "dispute_id": "DIS-123456789",
  "evidence_required": true,
  "evidence_due_date": "2026-01-08",
  "notes": "Customer claims unauthorized charge"
}

Response (200 OK):

json
{
  "message": "Payment dispute recorded successfully",
  "data": {
    "id": 789,
    "payment_number": "PAY-12345678",
    "status": "disputed",
    "disputed_at": "2025-12-25T00:00:00Z",
    "dispute": {
      "id": "DIS-123456789",
      "reason": "fraudulent",
      "amount": 347.47,
      "dispute_date": "2025-12-25",
      "evidence_due_date": "2026-01-08",
      "status": "open"
    },
    "funds_held": true,
    "action_required": "submit_evidence"
  }
}

Dispute Reasons

Common Dispute Reasons:

  • fraudulent - Customer claims unauthorized charge
  • unrecognized - Customer doesn't recognize charge
  • duplicate - Customer charged twice
  • product_not_received - Product never delivered
  • product_unacceptable - Product defective/not as described
  • credit_not_processed - Refund not received
  • subscription_cancelled - Charged after cancellation
  • other - Other reason

Submitting Dispute Evidence

json
POST /api/v1/sales/payments/{payment}/dispute/submit-evidence
{
  "evidence_type": "shipping_documentation",
  "evidence_files": [
    "tracking_proof.pdf",
    "delivery_signature.pdf",
    "invoice_copy.pdf"
  ],
  "evidence_text": "Customer signed for delivery on 12/20/2025. Tracking number 1Z999AA10123456784 shows delivered. Invoice INV-20251217-001 attached.",
  "customer_communication": [
    "email_confirmation_12_17.pdf",
    "shipping_notification_12_18.pdf"
  ]
}

Viewing Failed Payments

Endpoint: GET /api/v1/sales/payments/failed

Response (200 OK):

json
{
  "data": [
    {
      "id": 791,
      "payment_number": "PAY-12345680",
      "status": "failed",
      "amount": 299.00,
      "method": "credit_card",
      "failure_reason": "insufficient_funds",
      "failed_at": "2025-12-18T11:00:00Z",
      "retry_count": 2,
      "can_retry": true,
      "customer": {
        "id": 43,
        "company_name": "Beta Corp"
      }
    }
  ],
  "meta": {
    "total_failed": 1,
    "total_failed_amount": 299.00,
    "retryable_count": 1
  }
}

Viewing Disputed Payments

Endpoint: GET /api/v1/sales/payments/disputed

Response (200 OK):

json
{
  "data": [
    {
      "id": 789,
      "payment_number": "PAY-12345678",
      "status": "disputed",
      "amount": 347.47,
      "dispute_reason": "fraudulent",
      "disputed_at": "2025-12-25T00:00:00Z",
      "evidence_due_date": "2026-01-08",
      "days_to_respond": 14,
      "requires_urgent_action": false
    }
  ],
  "meta": {
    "total_disputed": 1,
    "total_disputed_amount": 347.47,
    "evidence_required": 1,
    "urgent_disputes": 0
  }
}

Payment Transactions

View Transaction History

Endpoint: GET /api/v1/sales/payments/{payment}/transactions

Authentication: Required (Bearer token)

Purpose: View complete transaction history for a payment

Response (200 OK):

json
{
  "data": [
    {
      "id": 1001,
      "type": "authorization",
      "amount": 347.47,
      "status": "succeeded",
      "gateway_transaction_id": "auth_1234567890",
      "created_at": "2025-12-18T09:00:00Z"
    },
    {
      "id": 1002,
      "type": "capture",
      "amount": 347.47,
      "status": "succeeded",
      "gateway_transaction_id": "ch_1234567890",
      "created_at": "2025-12-18T14:30:00Z"
    },
    {
      "id": 1003,
      "type": "refund",
      "amount": -100.00,
      "status": "succeeded",
      "gateway_transaction_id": "re_1234567890",
      "created_at": "2025-12-19T10:00:00Z"
    }
  ],
  "meta": {
    "total_transactions": 3,
    "net_amount": 247.47
  }
}

Transaction Types

Authorization:

  • Reserves funds
  • Does not transfer money
  • Expires after hold period

Capture:

  • Transfers reserved funds
  • Completes payment
  • Creates settlement

Refund:

  • Returns funds to customer
  • Reverses capture
  • May have fees

Void:

  • Cancels authorization
  • Releases reserved funds
  • No money transferred

Chargeback:

  • Customer dispute
  • Funds held/reversed
  • Requires evidence

Payment Reconciliation

Payment Statistics

Endpoint: GET /api/v1/sales/payments/statistics

Query Parameters:

  • from_date (date) - Start date
  • to_date (date) - End date
  • method (string) - Filter by payment method
  • status (string) - Filter by status

Response (200 OK):

json
{
  "data": {
    "period": {
      "from": "2025-12-01",
      "to": "2025-12-31"
    },
    "payment_counts": {
      "total": 1247,
      "completed": 1156,
      "failed": 45,
      "disputed": 3,
      "refunded": 23,
      "pending": 20
    },
    "financial_metrics": {
      "total_processed": 1245678.90,
      "total_refunded": 23456.78,
      "total_fees": 34567.89,
      "net_revenue": 1187654.23,
      "average_transaction": 998.87
    },
    "method_breakdown": {
      "credit_card": {
        "count": 856,
        "amount": 876543.21,
        "percentage": 70.4
      },
      "bank_transfer": {
        "count": 234,
        "amount": 234567.89,
        "percentage": 18.8
      },
      "paypal": {
        "count": 157,
        "amount": 134567.80,
        "percentage": 10.8
      }
    },
    "success_metrics": {
      "success_rate": 96.2,
      "failure_rate": 3.6,
      "dispute_rate": 0.2,
      "average_processing_time_seconds": 4.5
    }
  }
}

Payment Activities

Endpoint: GET /api/v1/sales/payments/{payment}/activities

Response (200 OK):

json
{
  "data": [
    {
      "id": 5001,
      "type": "payment_refunded",
      "description": "Partial refund issued - $100.00",
      "user": {
        "id": 5,
        "name": "Jane Manager"
      },
      "metadata": {
        "refund_amount": 100.00,
        "refund_reason": "partial_return"
      },
      "created_at": "2025-12-19T10:00:00Z"
    },
    {
      "id": 5000,
      "type": "payment_completed",
      "description": "Payment processed successfully",
      "user": {
        "id": null,
        "name": "System"
      },
      "metadata": {
        "gateway": "stripe",
        "transaction_id": "ch_1234567890"
      },
      "created_at": "2025-12-18T14:30:00Z"
    },
    {
      "id": 4999,
      "type": "payment_authorized",
      "description": "Payment authorized",
      "user": {
        "id": 3,
        "name": "John Sales"
      },
      "metadata": {
        "authorization_code": "AUTH-456789"
      },
      "created_at": "2025-12-18T09:00:00Z"
    }
  ]
}

Best Practices

  1. Refund Promptly: Process refunds quickly to maintain customer satisfaction

  2. Document Everything: Record detailed reasons for refunds, cancellations, and disputes

  3. Monitor Dispute Rate: High dispute rates may indicate fraud or customer service issues

  4. Retry Intelligently: Use exponential backoff for automatic payment retries

  5. Track Transaction History: Maintain complete audit trail for compliance

  6. Respond to Disputes Quickly: Submit evidence before deadline to avoid automatic loss

  7. Reconcile Daily: Match payment records with gateway settlements daily

  8. Handle Partial Refunds Carefully: Ensure accounting properly reflects partial refunds

  9. Test Refund Flows: Verify refund processing in test environment before production

  10. Notify Customers: Always inform customers of refunds, cancellations, and disputes

Documentation for SynthesQ CRM/ERP Platform