---
title: "Create vendor refund"
method: POST
path: "/v1/platform/businesses/{business_id}/vendor-refunds/"
tags: ["Vendor Refunds"]
---

# Create vendor refund

`POST /v1/platform/businesses/{business_id}/vendor-refunds/`

## Request

- Base URL: `https://docs.thredfi.com` (the document declares no server; this is the origin it was published from)
- URL: `https://docs.thredfi.com/v1/platform/businesses/{business_id}/vendor-refunds/`
- Auth: one of:
  - HTTP bearer
  - HTTP bearer
  - HTTP basic
  - HTTP bearer
  - HTTP bearer

Create a new vendor refund record (parent transaction).

        **Idempotency**: Uses `external_id` field - duplicate requests with the same
        `external_id` will return HTTP 200 with the existing refund instead of creating
        a duplicate.

        **Required Fields:**
        - `vendor_id`: UUID of the vendor issuing the refund
        - `total_refunded_amount_cents`: Total amount being refunded in cents (e.g., 10050 for £100.50)
        - `currency`: ISO 4217 currency code (EUR, GBP, USD)

        **Optional Fields:**
        - `external_id`: Your system's unique identifier (for idempotency)
        - `reference_number`: External reference number
        - `refund_type`: Type of refund (overpayment, billing_error, goods_return, etc.)
        - `refund_date`: Date of refund (defaults to today)
        - `description`: Detailed description
        - `memo`: Internal memo/notes
        - `reason`: Reason for the refund
        - `metadata`: Additional structured data (JSON object)
        - `allocations`: Array of allocations to create with the refund
        - `payments`: Array of payments to create with the refund
        - `document`: Optional document upload (multipart field `file` with optional document_type, upload_source, metadata, tags)

        **Common Scenarios:**
        1. **Overpayment refund** - Vendor returns excess payment
           ```json
           {
             "vendor_id": "uuid",
             "total_refunded_amount_cents": 15000,
             "currency": "GBP",
             "refund_type": "overpayment",
             "description": "Refund of overpayment"
           }
           ```

        2. **Billing error** - Vendor refunds due to billing mistake
           ```json
           {
             "vendor_id": "uuid",
             "total_refunded_amount_cents": 50000,
             "currency": "GBP",
             "refund_type": "billing_error",
             "reference_number": "REF-12345",
             "allocations": [{
               "allocation_type": "bill",
               "bill_id": "bill-uuid",
               "amount_cents": 50000
             }]
           }
           ```

        3. **Complete refund with payment** - Create refund with allocation and payment in one request
           ```json
           {
             "vendor_id": "uuid",
             "total_refunded_amount_cents": 100000,
             "currency": "GBP",
             "external_id": "my-refund-123",
             "allocations": [{
               "allocation_type": "bill",
               "bill_id": "bill-uuid",
               "amount_cents": 100000
             }],
             "payments": [{
               "refunded_amount_cents": 100000,
               "payment_method": "bank_transfer",
               "processor": "wise"
             }]
           }
           ```

        **Returns:**
        - HTTP 201: Refund created successfully
        - HTTP 200: Existing refund (idempotent - same external_id)
        - HTTP 400: Validation error

## Path parameters

- `business_id` string, required

## Request body

- CreateVendorRefundRequest: Serializer for creating vendor refunds. Handles validation and conversion of amounts from base units to cents.
  - `vendor_id` string, uuid, required: Vendor UUID
  - `external_id` string: External/partner refund ID for idempotency
  - `refund_type` 'overpayment' | 'credit_balance' | 'duplicate_payment' | 'billing_error' | 'goods_return' | 'service_cancellation' | 'other': Type/reason for the refund * `overpayment` - overpayment * `credit_balance` - credit_balance * `duplicate_payment` - duplicate_payment * `billing_error` - billing_error * `goods_return` - goods_return * `service_cancellation` - service_cancellation * `other` - other
  - `reference_number` string: External reference number
  - `total_refunded_amount_cents` integer, required: Total refunded amount in cents (e.g., 10050 for €100.50)
  - `currency` 'EUR' | 'GBP' | 'USD': ISO 4217 currency code * `EUR` - EUR * `GBP` - GBP * `USD` - USD
  - `refund_date` string, date: Date when refund was issued (ISO date: YYYY-MM-DD)
  - `description` string: Description of the refund reason or context
  - `memo` string: Internal memo or notes about this refund
  - `reason` string: Detailed explanation for the refund (max 500 characters)
  - `metadata` unknown
  - `allocations` CreateVendorRefundAllocationRequest[], nullable
    - `allocation_type` 'bill' | 'payment' | 'credit', required: Type of allocation: 'bill' (apply to bill), 'payment' (refund payment), or 'credit' (credit balance) * `bill` - bill * `payment` - payment * `credit` - credit
    - `amount_cents` integer, required: Allocation amount in cents (e.g., 10050 for €100.50)
    - `bill_id` string, uuid, nullable: Bill ID if allocation_type is 'bill'
    - `bill_payment_id` string, uuid, nullable: Bill payment ID if allocation_type is 'payment'
    - `description` string: Allocation description or notes
    - `metadata` unknown
  - `payments` CreateVendorRefundPaymentRequest[], nullable
    - `payment_reference` string: Your internal payment reference or tracking number
    - `refunded_amount_cents` integer, required: Refunded amount in cents
    - `processing_fee_cents` integer: Processing fee in cents
    - `payment_method` 'bank_transfer' | 'ach' | 'wire' | 'check' | 'credit_card' | 'cash' | 'other': Payment method: bank_transfer, ach, wire, check, credit_card, cash, other * `bank_transfer` - bank_transfer * `ach` - ach * `wire` - wire * `check` - check * `credit_card` - credit_card * `cash` - cash * `other` - other
    - `processor` 'stripe' | 'wise' | 'paypal' | 'bank_transfer' | 'internal': Payment processor: stripe, wise, paypal, bank_transfer, internal * `stripe` - stripe * `wise` - wise * `paypal` - paypal * `bank_transfer` - bank_transfer * `internal` - internal
    - `payment_date` string, date: Date when payment was made (ISO date: YYYY-MM-DD)
    - `description` string: Payment description or context
    - `memo` string: Internal memo or notes
    - `metadata` unknown
  - `document` VendorRefundDocumentUploadRequest: Vendor refund specific document upload payload.
    - `file` string, binary
    - `document_type` string
    - `upload_source` string
    - `metadata` unknown
    - `tags` unknown

## Response `201`

- VendorRefund: Comprehensive serializer for vendor refund responses. Includes all refund details plus related allocations and payments.
  - `id` string, uuid, required: Unique vendor refund identifier
  - `vendor_id` string, uuid, required: UUID of the vendor who issued the refund
  - `vendor_name` string, required: Vendor company name
  - `external_id` string: Your external system identifier for idempotency
  - `refund_type` 'overpayment' | 'credit_balance' | 'duplicate_payment' | 'billing_error' | 'goods_return' | 'service_cancellation' | 'other': Refund type: overpayment, credit_balance, billing_error, goods_return, duplicate_payment, service_cancellation, other * `overpayment` - Overpayment Refund * `credit_balance` - Credit Balance Refund * `duplicate_payment` - Duplicate Payment * `billing_error` - Billing Error * `goods_return` - Goods Return * `service_cancellation` - Service Cancellation * `other` - Other
  - `reference_number` string: External reference number for this refund
  - `refund_date` string, date: Date when refund was issued
  - `expected_completion_date` string, date, nullable: Expected date for refund completion
  - `total_refunded_amount` integer, required: Total refunded amount in cents
  - `allocated_amount` integer, required: Total allocated amount in cents
  - `unallocated_amount` integer, required: Remaining unallocated amount in cents
  - `currency` 'EUR' | 'GBP' | 'USD' | 'SEK' | 'NOK' | 'DKK' | 'ISK' | 'MYR' | 'SGD': Refund currency (EUR, GBP, USD) * `EUR` - Euro * `GBP` - British Pound * `USD` - US Dollar * `SEK` - Swedish Krona * `NOK` - Norwegian Krone * `DKK` - Danish Krone * `ISK` - Icelandic Króna * `MYR` - Malaysian Ringgit * `SGD` - Singapore Dollar
  - `status` 'pending' | 'partially_allocated' | 'allocated' | 'completed' | 'cancelled': Refund status: pending, partially_allocated, allocated, completed, cancelled (computed from allocations) * `pending` - Pending * `partially_allocated` - Partially Allocated * `allocated` - Allocated * `completed` - Completed * `cancelled` - Cancelled
  - `description` string: Description of the refund reason or context
  - `memo` string: Internal memo or notes
  - `reason` string: Detailed explanation for the refund
  - `metadata` unknown
  - `allocations` VendorRefundAllocationResponse[], required
    - `id` string, uuid, required: Unique allocation identifier
    - `allocation_type` 'bill' | 'payment' | 'credit': Type of allocation: bill, payment, or credit * `bill` - Applied to Bill * `payment` - Refund of Payment * `credit` - Credit Balance
    - `amount` integer, required: Allocated amount in cents
    - `bill_id` string, uuid, required: Bill ID if allocated to bill
    - `bill_number` string, required: Bill number if allocated to bill
    - `bill_outstanding_balance_cents` integer, required: Bill outstanding balance in cents if allocated to bill
    - `bill_payment_id` string, uuid, required: Bill payment ID if allocated to payment
    - `allocation_date` string, date-time: When allocation was created
    - `description` string: Allocation description or notes
    - `metadata` unknown
    - `created_at` string, date-time, required: Allocation creation timestamp
    - `updated_at` string, date-time, required: Last update timestamp
    - `target_description` string, required: Human-readable description of allocation target
  - `vendor_refund_payments` VendorRefundPaymentResponse[], required
    - `id` string, uuid, required: Unique vendor refund payment identifier
    - `vendor_refund_id` string, uuid, required: ID of the vendor refund this payment belongs to
    - `payment_reference` string: Your internal payment reference
    - `processor_payment_id` string: External processor payment ID
    - `payment_date` string, date: Date when payment was made
    - `refunded_amount` integer, required: Refunded amount in cents
    - `processing_fee` integer, required: Processing fee in cents
    - `net_amount` integer, required: Net amount after fees in cents
    - `payment_method` 'bank_transfer' | 'ach' | 'wire' | 'check' | 'credit_card' | 'cash' | 'other': Payment method: bank_transfer, ach, wire, check, credit_card, cash, other * `bank_transfer` - Bank Transfer * `ach` - ACH Transfer * `wire` - Wire Transfer * `check` - Check * `credit_card` - Credit Card Reversal * `cash` - Cash * `other` - Other
    - `processor` 'stripe' | 'wise' | 'paypal' | 'bank_transfer' | 'internal': Payment processor: stripe, wise, paypal, bank_transfer, internal * `stripe` - Stripe * `wise` - Wise (TransferWise) * `paypal` - PayPal * `bank_transfer` - Direct Bank Transfer * `internal` - Internal Processing
    - `status` 'pending' | 'processing' | 'completed' | 'failed' | 'cancelled': Payment status: pending, processing, completed, failed, cancelled * `pending` - Pending * `processing` - Processing * `completed` - Completed * `failed` - Failed * `cancelled` - Cancelled
    - `submitted_at` string, date-time, nullable: When payment was submitted for processing
    - `completed_at` string, date-time, nullable: When payment completed successfully
    - `failed_at` string, date-time, nullable: When payment failed
    - `failure_reason` string: Reason for payment failure
    - `description` string: Payment description
    - `memo` string: Internal memo
    - `metadata` unknown
    - `transaction_tags` unknown
    - `reconciled_bank_transactions` EntityReconciliationDetail[], required: Bank transactions this vendor refund payment is reconciled to
      - `payment_type` string
      - `bank_transaction_id` string, uuid, required
      - `bank_transaction_date` string, date-time, required
      - `bank_transaction_amount_cents` integer, required
      - `bank_transaction_direction` string, required
      - `reconciled_amount_cents` integer, required
      - `reconciliation_link_id` string, uuid, required
      - `reconciled_at` string, date-time, required
      - `currency` string, required
      - `bank_account_name` string
      - `notes` string
    - `created_at` string, date-time, required: Payment creation timestamp
    - `updated_at` string, date-time, required: Last update timestamp
  - `document` DocumentFileUrl, required: Serializer for document file URL with metadata.
    - `url` string, uri, required: Presigned URL for document download
    - `expires_in` integer, required: Seconds until URL expires
    - `document_id` string, uuid, required: Document UUID
    - `file_name` string, required: Original document filename
    - `file_size` integer, required: File size in bytes
    - `mime_type` string, required: MIME type of the document
  - `created_at` string, date-time, required: Refund creation timestamp
  - `updated_at` string, date-time, required: Last update timestamp

## Other responses

- `400`: Validation errors in request data
- `401`: Authentication required - missing or invalid API key
- `403`: Permission denied - insufficient privileges
- `404`: Resource not found
- `409`: Conflict - resource already exists or invalid state transition
- `422`: Unprocessable entity - business logic validation failed
- `500`: Internal server error

---

[API](https://skmtc.dev/thredfi/apis/thredfi-accounting-platform-api.md) - [All operations](https://skmtc.dev/thredfi/apis/thredfi-accounting-platform-api/llms.txt) - [OpenAPI document](https://skmtc.dev/thredfi/apis/thredfi-accounting-platform-api/revisions/0c1918254db3?raw)
