{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://futa.invalid/contracts/refund-event.v1.json",
  "title": "Refund event v1",
  "description": "A refund changed state: one event per state the refund reaches, its type refund. and the state in lower case. Refunds asked for in the portal are sent too. A notice, not the record: GET /v1/refunds/{id} is authoritative.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "id",
    "type",
    "occurred_at",
    "schema_version",
    "data"
  ],
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "description": "The event's id. The same event may arrive more than once (a retry or a replay): deduplicate on it."
    },
    "schema_version": {
      "const": 1
    },
    "type": {
      "type": "string",
      "pattern": "^refund\\.(pending_approval|queued|processing|uncertain|completed|failed|rejected|expired)$"
    },
    "occurred_at": {
      "type": "string",
      "format": "date-time"
    },
    "data": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "payment_id",
        "merchant_id",
        "amount",
        "currency",
        "state",
        "reason",
        "merchant_reason",
        "created_at",
        "issuer_reference",
        "sequence",
        "escalated",
        "sandbox",
        "approval"
      ],
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid",
          "description": "The refund's id, as POST /v1/payments/{id}/refunds answered it."
        },
        "payment_id": {
          "type": "string",
          "format": "uuid",
          "description": "The refunded payment's id, which also names the payment of a refund asked for in the portal."
        },
        "merchant_id": {
          "type": "string"
        },
        "amount": {
          "type": "integer",
          "minimum": 1,
          "maximum": 9000000000000,
          "description": "ISO minor units in the payment's currency; CDF in whole francs."
        },
        "currency": {
          "enum": [
            "USD",
            "CDF"
          ]
        },
        "state": {
          "enum": [
            "PENDING_APPROVAL",
            "QUEUED",
            "PROCESSING",
            "UNCERTAIN",
            "COMPLETED",
            "FAILED",
            "REJECTED",
            "EXPIRED"
          ],
          "description": "PENDING_APPROVAL waits for a person other than the requester to approve it in the portal; QUEUED, PROCESSING and UNCERTAIN are still open; COMPLETED and FAILED are the issuer's outcome; REJECTED and EXPIRED (not approved in time) end it without sending anything."
        },
        "reason": {
          "type": "string",
          "description": "Futa's code for the state (for example AWAITING_FUNDS, ISSUER_COMPLETED, APPROVAL_REJECTED)."
        },
        "merchant_reason": {
          "type": "string",
          "description": "The reason given when the refund was asked for."
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "issuer_reference": {
          "type": [
            "string",
            "null"
          ],
          "description": "The issuer's reference for the refund, once it states one."
        },
        "sequence": {
          "type": "integer",
          "minimum": 0,
          "description": "The refund's version at this state, rising with each change: apply an event only when its sequence is above the last one applied for that refund."
        },
        "escalated": {
          "type": "boolean"
        },
        "sandbox": {
          "const": true
        },
        "approval": {
          "type": [
            "object",
            "null"
          ],
          "description": "The approval the refund needed above the merchant's threshold, null otherwise.",
          "additionalProperties": false,
          "required": [
            "expires_at",
            "requested_by",
            "approved_by",
            "rejected_by",
            "decided_at"
          ],
          "properties": {
            "expires_at": {
              "type": "string",
              "format": "date-time"
            },
            "requested_by": {
              "type": "string",
              "description": "The team actor who asked: user:<subject> for a person, key:<id> for an API key."
            },
            "approved_by": {
              "type": [
                "string",
                "null"
              ]
            },
            "rejected_by": {
              "type": [
                "string",
                "null"
              ]
            },
            "decided_at": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time"
            }
          }
        }
      }
    }
  }
}
