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

# Refund a sale

> Refunds the sale recorded under `external_id`, which is required, and shrinks or claws back its commission. Send `refunded_amount` (major units) or `refunded_amount_cents` (minor units, converted in the sale's currency) as the TOTAL refunded so far on that order, not the amount of this one refund. If it is below the sale amount the refund is partial and the commission shrinks in proportion. If it is at or above the sale amount, or you leave it out, the whole sale is refunded. Commission that was already paid becomes a clawback. A refund that arrives before its sale is held and applied when the sale arrives; if the held amount covers the whole sale, the sale is fully refunded. A refund is always in the sale's currency. You can leave `currency` out, but if you send one that differs from the sale's you get `422 currency_mismatch` and nothing is recorded. A refund with an amount that arrives before its sale has no sale currency to go by, so it needs `currency` (`422 currency_required` without one). Safe to retry. MCP connector tokens get `403 insufficient_scope`.



## OpenAPI

````yaml /openapi.yaml post /v1/track/refund
openapi: 3.1.0
info:
  title: Affixo API
  version: 1.0.0
  description: |
    The Affixo REST API for affiliate program management and server-to-server
    conversion tracking.

    All requests authenticate with a workspace key (`sa_live_…`) as a Bearer
    token. Scopes: `read` / `write` / `track` / `*`.
servers:
  - url: https://go.affixo.dev
    description: Production
security: []
tags:
  - name: Affiliates
    description: Manage affiliates (workspace key)
  - name: Campaigns
    description: Create and configure campaigns + commission rules (workspace key)
  - name: Links
    description: Manage referral links (workspace key)
  - name: Risk
    description: AI risk assessments for fraud triage (workspace key)
  - name: Commissions
    description: Approve, deny, and manage commissions (workspace key)
  - name: Conversions
    description: Re-attribute and manage conversions (workspace key)
  - name: Webhooks
    description: Manage webhook endpoint subscriptions (workspace key)
  - name: Reports
    description: Aggregated reporting data (workspace key)
  - name: Resources
    description: Read campaigns, commissions, conversions, payouts (workspace key)
  - name: Referrals
    description: >-
      Move a referred customer to another affiliate, and send test referrals
      (workspace key)
  - name: Tracking
    description: >-
      Server-to-server click & conversion tracking (workspace key, scope
      "track")
  - name: Products
    description: >-
      Your Stripe product catalog and which products earn commission (workspace
      key)
paths:
  /v1/track/refund:
    post:
      tags:
        - Tracking
      summary: Refund a sale
      description: >-
        Refunds the sale recorded under `external_id`, which is required, and
        shrinks or claws back its commission. Send `refunded_amount` (major
        units) or `refunded_amount_cents` (minor units, converted in the sale's
        currency) as the TOTAL refunded so far on that order, not the amount of
        this one refund. If it is below the sale amount the refund is partial
        and the commission shrinks in proportion. If it is at or above the sale
        amount, or you leave it out, the whole sale is refunded. Commission that
        was already paid becomes a clawback. A refund that arrives before its
        sale is held and applied when the sale arrives; if the held amount
        covers the whole sale, the sale is fully refunded. A refund is always in
        the sale's currency. You can leave `currency` out, but if you send one
        that differs from the sale's you get `422 currency_mismatch` and nothing
        is recorded. A refund with an amount that arrives before its sale has no
        sale currency to go by, so it needs `currency` (`422 currency_required`
        without one). Safe to retry. MCP connector tokens get `403
        insufficient_scope`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - external_id
              properties:
                external_id:
                  type: string
                  example: order_1234
                refunded_amount:
                  type: number
                  example: 25
                  description: Total refunded so far, in major units.
                refunded_amount_cents:
                  type: integer
                  minimum: 0
                  example: 2500
                  description: >-
                    Total refunded so far, in minor units. Don't send it
                    together with `refunded_amount`.
                currency:
                  type: string
                  example: usd
                  description: >-
                    The sale's currency. Optional once the sale is recorded, and
                    must match it. Required when the refund carries an amount
                    and its sale hasn't arrived yet.
      responses:
        '200':
          description: Refund recorded
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                    example: true
                  conversion_id:
                    type: string
                  refund:
                    type: string
                    enum:
                      - full
                      - partial
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '422':
          description: >-
            The currency doesn't work for this refund. Nothing was recorded.
            `currency_mismatch`: the body names a currency other than the sale's
            (`sale_currency` says which). `currency_required`: the refund
            carries an amount, its sale hasn't arrived yet, and no `currency`
            was sent.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    enum:
                      - currency_mismatch
                      - currency_required
                  message:
                    type: string
                  sale_currency:
                    type: string
                    example: usd
                    description: Present on currency_mismatch.
        '500':
          $ref: '#/components/responses/ServerError'
      security:
        - WorkspaceKey: []
components:
  responses:
    BadRequest:
      description: Invalid or missing parameters
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: invalid_json
    Unauthorized:
      description: Missing or invalid bearer token
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: unauthorized
    ServerError:
      description: Internal error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: conversion_failed
  schemas:
    Error:
      type: object
      properties:
        error:
          type: string
        need:
          type: string
          description: Present on insufficient_scope.
        detail:
          type: string
  securitySchemes:
    WorkspaceKey:
      type: http
      scheme: bearer
      description: 'Workspace API key, e.g. `sa_live_…`. Scopes: read / write / track / *.'

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.