> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stablepayfi.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Create refund

> Create a refund. Pass exactly one of `charge` or `payment_id`: use `charge` for a normal payment refund, where it identifies the normal payment to refund; use `payment_id` for a subscription refund, where it identifies the payment generated by the subscription invoice. Newly created refunds currently enter the `processing` state.



## OpenAPI

````yaml /en/api/refund-openapi.json post /api/v1/refunds/create
openapi: 3.1.0
info:
  title: StablePay Refund API
  version: '2026-04-14'
  summary: 'StablePay refund endpoints: create, retrieve, and cancel refunds.'
  description: >-
    OpenAPI specification for the StablePay refund endpoints.


    ## Authentication


    Every endpoint requires both a **Bearer API Key** and signature headers:


    - `Authorization: Bearer {api_key}`

    - `X-StablePay-Timestamp`: Unix timestamp in seconds

    - `X-StablePay-Nonce`: Random string (UUID recommended) used for replay
    protection

    - `X-StablePay-Signature`: HMAC-SHA256 signature


    ## Signing rules


    The signing string is `{timestamp}.{nonce}.{requestBody}`:


    - `POST` requests: `requestBody` is the raw JSON payload string

    - `GET` requests: `requestBody` is the empty string


    Compute HMAC-SHA256 of the signing string using the merchant API Secret, and
    use the lowercase hex digest as `X-StablePay-Signature`.


    ## Amount precision


    All amount fields are expressed in the smallest unit of the currency. USDT
    and USDC both use 6 decimal places (i.e., 1 USDT = 1,000,000).
servers:
  - url: https://api.stablepay.co
    description: Production
security:
  - bearerAuth: []
    stablepayTimestamp: []
    stablepayNonce: []
    stablepaySignature: []
tags:
  - name: Refunds
    description: Create, retrieve, and cancel refunds.
paths:
  /api/v1/refunds/create:
    post:
      tags:
        - Refunds
      summary: Create refund
      description: >-
        Create a refund. Pass exactly one of `charge` or `payment_id`: use
        `charge` for a normal payment refund, where it identifies the normal
        payment to refund; use `payment_id` for a subscription refund, where it
        identifies the payment generated by the subscription invoice. Newly
        created refunds currently enter the `processing` state.
      operationId: createRefund
      parameters:
        - $ref: '#/components/parameters/XStablePayTimestamp'
        - $ref: '#/components/parameters/XStablePayNonce'
        - $ref: '#/components/parameters/XStablePaySignature'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateRefundRequest'
            examples:
              payment_refund:
                summary: Payment refund
                value:
                  charge: 2026012811010010133371000000xxxx
                  refund_id: refund_20250101001
                  amount: 5000000
                  currency: USDT
                  reason: requested_by_customer
                  description: Customer requested refund
                  metadata:
                    customer_id: customer_123
                    refund_note: Product quality issue
              subscription_refund:
                summary: Subscription refund
                value:
                  payment_id: 2026012811010010133371000000xxxx
                  refund_id: refund_20250101002
                  amount: 1000000
                  currency: USDT
                  reason: duplicate
        description: Pass exactly one of `charge` or `payment_id`; do not send both fields.
      responses:
        '201':
          description: Refund created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Refund'
        '400':
          description: >-
            Invalid request (missing parameters, amount exceeds limit, or
            session status does not allow refunds)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Authentication failed (invalid API key or signature)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Access denied
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Payment session does not exist
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: Too many requests or daily refund limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Server error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  parameters:
    XStablePayTimestamp:
      name: X-StablePay-Timestamp
      in: header
      required: true
      description: Unix timestamp in seconds. Must be within 5 minutes of server time.
      schema:
        type: string
      example: '1735689600'
    XStablePayNonce:
      name: X-StablePay-Nonce
      in: header
      required: true
      description: Replay-protection nonce, 16-64 characters. Use a fresh UUID per request.
      schema:
        type: string
        minLength: 16
        maxLength: 64
      example: 550e8400-e29b-41d4-a716-446655440000
    XStablePaySignature:
      name: X-StablePay-Signature
      in: header
      required: true
      description: >-
        Lowercase hex HMAC-SHA256 of `{timestamp}.{nonce}.{requestBody}` signed
        with the merchant API Secret. For GET requests, `requestBody` is an
        empty string.
      schema:
        type: string
      example: a1b2c3d4e5f6...
  schemas:
    CreateRefundRequest:
      type: object
      required:
        - refund_id
        - amount
        - currency
      properties:
        charge:
          type: string
          description: >-
            Use for normal payment refunds. Pass the normal payment ID to
            refund.
        payment_id:
          type: string
          description: >-
            Use for subscription refunds. Pass the payment ID generated by the
            subscription invoice.
        refund_id:
          type: string
          description: Merchant-defined unique refund ID used as the idempotency key.
        amount:
          type: integer
          format: int64
          minimum: 1
          description: Refund amount in minor units. Must be greater than 0.
        currency:
          type: string
          enum:
            - USDT
            - USDC
          description: >-
            Refund currency. The current request binding allows `USDT` or
            `USDC`.
        reason:
          type: string
          enum:
            - requested_by_customer
            - duplicate
            - fraudulent
            - expired_uncaptured
          description: Refund reason.
        description:
          type: string
          description: Refund description.
        refund_to_address:
          type: string
          description: Optional on-chain refund destination address.
        refund_to_address_id:
          type: integer
          format: int64
          description: >-
            Optional on-chain refund destination address ID; only values greater
            than 0 are used.
        metadata:
          type: object
          additionalProperties: true
          description: Merchant metadata.
      description: >-
        Exactly one of `charge` or `payment_id` is required. Use `charge` for
        normal payment refunds and `payment_id` for subscription refunds.
      oneOf:
        - title: Normal payment refund
          required:
            - charge
        - title: Subscription refund
          required:
            - payment_id
    Refund:
      type: object
      description: Refund object returned after creation.
      properties:
        refund_id:
          type: string
          description: Merchant-supplied refund ID.
        payment_id:
          type: string
          description: Payment identifier returned for subscription refund scenarios.
        order_id:
          type: string
          description: Merchant order ID, returned for normal payment refunds.
        amount:
          type: integer
          format: int64
          description: Refund amount in minor units.
        currency:
          type: string
          enum:
            - USDT
            - USDC
          description: Refund currency.
        status:
          $ref: '#/components/schemas/RefundStatus'
        reason:
          type: string
          enum:
            - requested_by_customer
            - duplicate
            - fraudulent
            - expired_uncaptured
          description: Refund reason.
        description:
          type: string
          description: Refund description.
        created_at:
          type: integer
          format: int64
          description: Refund creation time, Unix seconds.
        metadata:
          type: object
          additionalProperties: true
          description: Merchant metadata.
        invoice_id:
          type: string
          description: Invoice ID returned for subscription refunds.
        subscription_id:
          type: string
          description: Subscription ID returned for subscription refunds.
    ErrorResponse:
      type: object
      description: Error response.
      properties:
        error:
          type: object
          properties:
            type:
              type: string
              description: Error type.
            code:
              type: string
              description: Error code.
            message:
              type: string
              description: Error message.
            param:
              type: string
              description: Related parameter.
            doc_url:
              type: string
              description: Error documentation URL.
            decline_code:
              type: string
              description: Decline code.
            request_log_url:
              type: string
              description: Request log URL.
            charge:
              type: string
              description: Related payment ID.
        request_id:
          type: string
          description: Request ID.
        timestamp:
          type: integer
          format: int64
          description: Error timestamp in Unix seconds.
    RefundStatus:
      type: string
      enum:
        - pending
        - processing
        - completed
        - failed
        - canceled
      description: >-
        Refund status. Newly created refunds usually return `processing` in the
        current implementation.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API Key
      description: Bearer API Key, for example `Bearer sk_live_xxx`.
    stablepayTimestamp:
      type: apiKey
      in: header
      name: X-StablePay-Timestamp
      description: Unix timestamp in seconds. Must be within 5 minutes of server time.
    stablepayNonce:
      type: apiKey
      in: header
      name: X-StablePay-Nonce
      description: Replay-protection nonce, 16-64 characters. Use a fresh UUID per request.
    stablepaySignature:
      type: apiKey
      in: header
      name: X-StablePay-Signature
      description: >-
        Lowercase hex HMAC-SHA256 of `{timestamp}.{nonce}.{requestBody}` signed
        with the merchant API Secret. For GET requests, `requestBody` is an
        empty string.

````