{
  "openapi": "3.0.3",
  "info": {
    "title": "KatFacil Business Cards API",
    "version": "1.0.0",
    "description": "Official white-label API for business card creation, card management, recharge, transactions and signed webhooks. Test credentials allow safe reads. Live financial operations become available after administrator approval and the first qualifying successful deposit."
  },
  "servers": [
    {
      "url": "https://katfacil.com/api/v1",
      "description": "KatFacil production API"
    }
  ],
  "tags": [
    { "name": "Account", "description": "API status, activation and pricing" },
    { "name": "Cards", "description": "Create and manage business cards" },
    { "name": "Webhooks", "description": "Events sent by KatFacil to the business callback URL" }
  ],
  "security": [
    {
      "KatFacilKey": [],
      "KatFacilSecret": []
    }
  ],
  "paths": {
    "/cards": {
      "get": {
        "tags": ["Account"],
        "summary": "List cards and API status",
        "description": "Returns all non-demo cards owned by the authenticated business, the active API mode, live activation state and card creation limit. This safe read is available with valid test credentials.",
        "operationId": "listBusinessCards",
        "responses": {
          "200": {
            "description": "Cards and API status returned",
            "headers": { "X-Request-ID": { "$ref": "#/components/headers/RequestId" } },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CardListResponse" },
                "example": {
                  "data": {
                    "api_mode": "live",
                    "live_activation": { "activated": true, "first_deposit_required": true, "minimum_first_deposit": 25, "currency": "USD" },
                    "card_create_limit": 25,
                    "cards": [
                      { "id": 145, "external_id": "card_8f2d", "card_product": "mastercard_virtual", "brand": "Mastercard Virtual", "name_on_card": "JEAN ROODY DIE", "balance": 26, "currency": "USD", "masked_pan": "**** **** **** 1041", "expiry": "09/29", "status": "ACTIVE", "created_at": "2026-09-12T12:00:00Z" }
                    ]
                  },
                  "message": { "success": ["Business cards fetched successfully"] }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/ApprovalRequired" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/cards/charges": {
      "get": {
        "tags": ["Account"],
        "summary": "Get current card charges",
        "description": "Returns the authenticated business subscription plan and creation/recharge pricing for all supported products. Retrieve this resource before displaying or confirming a financial operation.",
        "operationId": "getBusinessCardCharges",
        "responses": {
          "200": {
            "description": "Current charges returned",
            "headers": { "X-Request-ID": { "$ref": "#/components/headers/RequestId" } },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ChargesResponse" },
                "example": {
                  "data": {
                    "api_mode": "live",
                    "live_activation": { "activated": true, "first_deposit_required": true, "minimum_first_deposit": 25, "currency": "USD" },
                    "wallet_currency": "USD",
                    "subscription_plan": "regular",
                    "products": [
                      {
                        "card_product": "mastercard_virtual",
                        "brand": "Mastercard",
                        "creation": { "requested_amount": 1, "initial_load": 1, "fixed_charge": 2, "percent_rate": 0, "percent_charge": 0, "bank_cost": 0, "total_charge": 2, "payable": 3 },
                        "recharge": { "requested_amount": 0, "fixed_charge": 1, "percent_rate": 1, "percent_charge": 0, "bank_cost": 0, "total_charge": 1, "payable": 1, "min_amount": 1, "max_amount": 2500 }
                      }
                    ]
                  },
                  "message": { "success": ["Business card charges fetched successfully"] }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/ApprovalRequired" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/cards/create": {
      "post": {
        "tags": ["Cards"],
        "summary": "Create a card",
        "description": "Creates one card for the verified business account. Requires an active subscription, live API activation, sufficient wallet balance and a unique UUID Idempotency-Key. Repeating an identical request with the same key returns the original result and does not create a duplicate card.",
        "operationId": "createBusinessCard",
        "parameters": [{ "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/CreateCardRequest" },
              "examples": {
                "mastercard": { "summary": "Mastercard virtual", "value": { "card_product": "mastercard_virtual" } },
                "visa": { "summary": "Visa virtual", "value": { "card_product": "visa_virtual" } }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Card created",
            "headers": { "X-Request-ID": { "$ref": "#/components/headers/RequestId" } },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CardMutationResponse" },
                "example": {
                  "data": {
                    "card": { "id": 145, "external_id": "card_8f2d", "card_product": "mastercard_virtual", "brand": "Mastercard Virtual", "name_on_card": "JEAN ROODY DIE", "balance": 1, "currency": "USD", "masked_pan": "**** **** **** 1041", "expiry": "09/29", "status": "ACTIVE", "created_at": "2026-09-12T12:00:00Z" },
                    "transaction_id": "PGB123456789",
                    "charge_summary": { "requested_amount": 1, "initial_load": 1, "fixed_charge": 2, "percent_rate": 0, "percent_charge": 0, "bank_cost": 0, "total_charge": 2, "payable": 3 }
                  },
                  "message": { "success": ["Business card created successfully"] }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/OperationFailed" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/LiveActivationRequired" },
          "422": { "$ref": "#/components/responses/ValidationFailed" },
          "429": { "$ref": "#/components/responses/DailyLimitReached" }
        }
      }
    },
    "/cards/{id}": {
      "get": {
        "tags": ["Cards"],
        "summary": "Get card details",
        "description": "Returns a card owned by the authenticated business. Full PAN, CVV, PIN, secrets, tokens and upstream service information are not returned.",
        "operationId": "getBusinessCard",
        "parameters": [{ "$ref": "#/components/parameters/CardId" }],
        "responses": {
          "200": {
            "description": "Card details returned",
            "headers": { "X-Request-ID": { "$ref": "#/components/headers/RequestId" } },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/SingleCardResponse" },
                "example": {
                  "data": { "card": { "id": 145, "external_id": "card_8f2d", "card_product": "mastercard_virtual", "brand": "Mastercard Virtual", "name_on_card": "JEAN ROODY DIE", "balance": 26, "currency": "USD", "masked_pan": "**** **** **** 1041", "expiry": "09/29", "status": "ACTIVE", "created_at": "2026-09-12T12:00:00Z" } },
                  "message": { "success": ["Business card details fetched successfully"] }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/CardNotFound" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/cards/{id}/transactions": {
      "get": {
        "tags": ["Cards"],
        "summary": "Get card transactions",
        "description": "Returns sanitized transactions for a card owned by the authenticated business.",
        "operationId": "getBusinessCardTransactions",
        "parameters": [
          { "$ref": "#/components/parameters/CardId" },
          { "name": "page", "in": "query", "required": false, "description": "Page number beginning at 1", "schema": { "type": "integer", "minimum": 1, "default": 1 } }
        ],
        "responses": {
          "200": {
            "description": "Transactions returned",
            "headers": { "X-Request-ID": { "$ref": "#/components/headers/RequestId" } },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/TransactionsResponse" },
                "example": {
                  "data": {
                    "card": { "id": 145, "external_id": "card_8f2d", "card_product": "mastercard_virtual", "brand": "Mastercard Virtual", "name_on_card": "JEAN ROODY DIE", "balance": 26, "currency": "USD", "masked_pan": "**** **** **** 1041", "expiry": "09/29", "status": "ACTIVE", "created_at": "2026-09-12T12:00:00Z" },
                    "transactions": [{ "id": "txn_9281", "type": "purchase", "amount": 12.5, "currency": "USD", "merchant": "Example Store", "status": "COMPLETED", "created_at": "2026-09-12T12:00:00Z" }]
                  },
                  "message": { "success": ["Business card transactions fetched successfully"] }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/CardNotFound" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/cards/fund": {
      "post": {
        "tags": ["Cards"],
        "summary": "Recharge a card",
        "description": "Moves the requested amount to a card. The business wallet must cover the amount plus applicable plan charges. Requires live activation and a unique UUID Idempotency-Key.",
        "operationId": "rechargeBusinessCard",
        "parameters": [{ "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/FundCardRequest" },
              "example": { "card_id": 145, "amount": 25 }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Card recharged",
            "headers": { "X-Request-ID": { "$ref": "#/components/headers/RequestId" } },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CardMutationResponse" },
                "example": {
                  "data": {
                    "card": { "id": 145, "external_id": "card_8f2d", "card_product": "mastercard_virtual", "brand": "Mastercard Virtual", "name_on_card": "JEAN ROODY DIE", "balance": 26, "currency": "USD", "masked_pan": "**** **** **** 1041", "expiry": "09/29", "status": "ACTIVE", "created_at": "2026-09-12T12:00:00Z" },
                    "transaction_id": "PGB123456790",
                    "charge_summary": { "requested_amount": 25, "fixed_charge": 1, "percent_rate": 1, "percent_charge": 0.25, "bank_cost": 0, "total_charge": 1.25, "payable": 26.25, "min_amount": 1, "max_amount": 2500 }
                  },
                  "message": { "success": ["Business card funded successfully"] }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/OperationFailed" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/LiveActivationRequired" },
          "404": { "$ref": "#/components/responses/CardNotFound" },
          "422": { "$ref": "#/components/responses/ValidationFailed" },
          "429": { "$ref": "#/components/responses/DailyLimitReached" }
        }
      }
    },
    "/cards/{id}/status": {
      "put": {
        "tags": ["Cards"],
        "summary": "Change card status",
        "description": "Single status operation for both directions. Send frozen to temporarily prevent card use or active to restore normal card use. Do not implement separate freeze, unfreeze or activation endpoints.",
        "operationId": "changeBusinessCardStatus",
        "parameters": [
          { "$ref": "#/components/parameters/CardId" },
          { "$ref": "#/components/parameters/IdempotencyKey" }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ChangeStatusRequest" },
              "examples": {
                "temporarilyPreventUse": { "summary": "Temporarily prevent card use", "value": { "status": "frozen" } },
                "restoreUse": { "summary": "Restore normal card use", "value": { "status": "active" } }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Card status updated",
            "headers": { "X-Request-ID": { "$ref": "#/components/headers/RequestId" } },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/SingleCardResponse" },
                "example": {
                  "data": { "card": { "id": 145, "external_id": "card_8f2d", "card_product": "mastercard_virtual", "brand": "Mastercard Virtual", "name_on_card": "JEAN ROODY DIE", "balance": 26, "currency": "USD", "masked_pan": "**** **** **** 1041", "expiry": "09/29", "status": "FROZEN", "created_at": "2026-09-12T12:00:00Z" } },
                  "message": { "success": ["Business card status updated successfully"] }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/OperationFailed" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/LiveActivationRequired" },
          "404": { "$ref": "#/components/responses/CardNotFound" },
          "422": { "$ref": "#/components/responses/ValidationFailed" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "KatFacilKey": { "type": "apiKey", "in": "header", "name": "X-KatFacil-Key", "description": "Business test or live API key." },
      "KatFacilSecret": { "type": "apiKey", "in": "header", "name": "X-KatFacil-Secret", "description": "Secret matching the supplied API key. Store only on a secure server." }
    },
    "headers": {
      "RequestId": { "description": "Unique request identifier for audit logs and support.", "schema": { "type": "string", "format": "uuid" } }
    },
    "parameters": {
      "CardId": { "name": "id", "in": "path", "required": true, "description": "KatFacil integer card ID returned by the API. Do not use external_id.", "schema": { "type": "integer", "minimum": 1 }, "example": 145 },
      "IdempotencyKey": { "name": "Idempotency-Key", "in": "header", "required": true, "description": "A unique UUID for this operation. Retry the same operation with the same UUID after a timeout; use a new UUID for a new operation.", "schema": { "type": "string", "format": "uuid" }, "example": "550e8400-e29b-41d4-a716-446655440000" }
    },
    "schemas": {
      "LiveActivation": {
        "type": "object",
        "required": ["activated", "first_deposit_required", "minimum_first_deposit", "currency"],
        "properties": {
          "activated": { "type": "boolean" },
          "first_deposit_required": { "type": "boolean" },
          "minimum_first_deposit": { "type": "number", "format": "double", "minimum": 0 },
          "currency": { "type": "string", "example": "USD" }
        }
      },
      "Card": {
        "type": "object",
        "required": ["id", "card_product", "balance", "currency", "masked_pan", "status"],
        "properties": {
          "id": { "type": "integer", "example": 145 },
          "external_id": { "type": "string", "nullable": true, "example": "card_8f2d" },
          "card_product": { "type": "string", "enum": ["mastercard_virtual", "visa_virtual"] },
          "brand": { "type": "string", "example": "Mastercard Virtual" },
          "name_on_card": { "type": "string", "example": "JEAN ROODY DIE" },
          "balance": { "type": "number", "format": "double", "example": 26 },
          "currency": { "type": "string", "example": "USD" },
          "masked_pan": { "type": "string", "example": "**** **** **** 1041" },
          "expiry": { "type": "string", "nullable": true, "example": "09/29" },
          "status": { "type": "string", "example": "ACTIVE" },
          "created_at": { "type": "string", "format": "date-time", "nullable": true }
        }
      },
      "ChargeSummary": {
        "type": "object",
        "properties": {
          "requested_amount": { "type": "number", "format": "double" },
          "initial_load": { "type": "number", "format": "double" },
          "fixed_charge": { "type": "number", "format": "double" },
          "percent_rate": { "type": "number", "format": "double" },
          "percent_charge": { "type": "number", "format": "double" },
          "bank_cost": { "type": "number", "format": "double" },
          "total_charge": { "type": "number", "format": "double" },
          "payable": { "type": "number", "format": "double" },
          "min_amount": { "type": "number", "format": "double" },
          "max_amount": { "type": "number", "format": "double" }
        }
      },
      "Message": { "type": "object", "additionalProperties": { "type": "array", "items": { "type": "string" } } },
      "CreateCardRequest": { "type": "object", "required": ["card_product"], "properties": { "card_product": { "type": "string", "enum": ["mastercard_virtual", "visa_virtual"] } } },
      "FundCardRequest": { "type": "object", "required": ["card_id", "amount"], "properties": { "card_id": { "type": "integer", "minimum": 1, "example": 145 }, "amount": { "type": "number", "format": "double", "minimum": 0.01, "maximum": 9999999.99, "example": 25 } } },
      "ChangeStatusRequest": { "type": "object", "required": ["status"], "properties": { "status": { "type": "string", "enum": ["frozen", "active"] } } },
      "CardTransaction": { "type": "object", "properties": { "id": { "type": "string", "nullable": true }, "type": { "type": "string" }, "amount": { "type": "number", "format": "double" }, "currency": { "type": "string" }, "merchant": { "type": "string", "nullable": true }, "status": { "type": "string" }, "created_at": { "type": "string", "nullable": true } } },
      "CardListResponse": { "type": "object", "properties": { "data": { "type": "object", "properties": { "api_mode": { "type": "string", "enum": ["test", "live"] }, "live_activation": { "$ref": "#/components/schemas/LiveActivation" }, "card_create_limit": { "type": "integer" }, "cards": { "type": "array", "items": { "$ref": "#/components/schemas/Card" } } } }, "message": { "$ref": "#/components/schemas/Message" } } },
      "SingleCardResponse": { "type": "object", "properties": { "data": { "type": "object", "properties": { "card": { "$ref": "#/components/schemas/Card" } } }, "message": { "$ref": "#/components/schemas/Message" } } },
      "CardMutationResponse": { "type": "object", "properties": { "data": { "type": "object", "properties": { "card": { "$ref": "#/components/schemas/Card" }, "transaction_id": { "type": "string" }, "charge_summary": { "$ref": "#/components/schemas/ChargeSummary" }, "idempotent_replay": { "type": "boolean" } } }, "message": { "$ref": "#/components/schemas/Message" } } },
      "TransactionsResponse": { "type": "object", "properties": { "data": { "type": "object", "properties": { "card": { "$ref": "#/components/schemas/Card" }, "transactions": { "type": "array", "items": { "$ref": "#/components/schemas/CardTransaction" } } } }, "message": { "$ref": "#/components/schemas/Message" } } },
      "ChargesResponse": { "type": "object", "properties": { "data": { "type": "object", "properties": { "api_mode": { "type": "string", "enum": ["test", "live"] }, "live_activation": { "$ref": "#/components/schemas/LiveActivation" }, "wallet_currency": { "type": "string" }, "subscription_plan": { "type": "string", "enum": ["regular", "partner", "vip"] }, "products": { "type": "array", "items": { "type": "object", "properties": { "card_product": { "type": "string", "enum": ["mastercard_virtual", "visa_virtual"] }, "brand": { "type": "string" }, "creation": { "$ref": "#/components/schemas/ChargeSummary" }, "recharge": { "$ref": "#/components/schemas/ChargeSummary" } } } } } }, "message": { "$ref": "#/components/schemas/Message" } } },
      "ErrorResponse": { "type": "object", "properties": { "data": { "type": "object", "nullable": true, "additionalProperties": true }, "message": { "$ref": "#/components/schemas/Message" } } },
      "WebhookPayload": { "type": "object", "required": ["id", "event", "created_at", "data"], "properties": { "id": { "type": "string", "format": "uuid" }, "event": { "type": "string", "enum": ["katfacil.webhook.test", "katfacil.card.created", "katfacil.card.authorization_requested", "katfacil.card.transaction_updated", "katfacil.card.funding_requested", "katfacil.card.funding_approved", "katfacil.card.status_updated"] }, "created_at": { "type": "string", "format": "date-time" }, "data": { "type": "object", "additionalProperties": true } } }
    },
    "responses": {
      "Unauthorized": { "description": "Missing or invalid API credentials", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "data": null, "message": { "error": ["Business API credentials are required."] } } } } },
      "ApprovalRequired": { "description": "Business API access is awaiting administrator approval", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "data": { "code": "BUSINESS_API_APPROVAL_REQUIRED", "request_id": "9a54d19c-76f6-4bf5-bfbe-d431ea714e88" }, "message": { "error": ["Your business API access is awaiting administrator approval."] } } } } },
      "LiveActivationRequired": { "description": "A qualifying first deposit is required before live financial operations", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "data": { "code": "LIVE_API_ACTIVATION_REQUIRED", "api_mode": "test", "live_activation": { "activated": false, "first_deposit_required": true, "minimum_first_deposit": 25, "currency": "USD" } }, "message": { "error": ["Complete a successful first deposit to activate live API operations."] } } } } },
      "ValidationFailed": { "description": "Invalid request fields or Idempotency-Key", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "data": null, "message": { "error": ["A valid UUID Idempotency-Key header is required."] } } } } },
      "CardNotFound": { "description": "Card not found or not owned by the authenticated business", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "data": null, "message": { "error": ["Card not found"] } } } } },
      "OperationFailed": { "description": "The operation failed a business rule or could not be completed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "data": null, "message": { "error": ["The card operation could not be completed right now."] } } } } },
      "RateLimited": { "description": "Per-minute API rate limit exceeded", "headers": { "X-Request-ID": { "$ref": "#/components/headers/RequestId" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "data": { "code": "API_RATE_LIMIT_EXCEEDED", "request_id": "9a54d19c-76f6-4bf5-bfbe-d431ea714e88", "retry_after": 42 }, "message": { "error": ["Too many API requests. Please try again shortly."] } } } } },
      "DailyLimitReached": { "description": "Card creation or recharge daily limit exceeded", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "cardLimit": { "value": { "data": { "code": "CARD_DAILY_LIMIT_EXCEEDED", "limit": 25, "used": 25, "remaining": 0 }, "message": { "error": ["Your daily card creation limit has been reached."] } } }, "rechargeLimit": { "value": { "data": { "code": "FUND_DAILY_LIMIT_EXCEEDED", "limit": 5000, "used": 4990, "remaining": 10 }, "message": { "error": ["This funding request exceeds your daily funding limit."] } } } } } } }
    }
  },
  "x-readme": {
    "explorer-enabled": true,
    "proxy-enabled": true,
    "samples-enabled": true
  },
  "x-katfacil-webhooks": {
    "callbackConfiguration": "Configure the HTTPS callback URL and signing secret in Business > Webhooks.",
    "headers": {
      "X-KatFacil-Delivery": "Unique UUID used for deduplication",
      "X-KatFacil-Signature": "sha256= followed by the HMAC SHA-256 hex digest of the exact raw body"
    },
    "receiverRules": ["Verify the signature using the exact raw request body", "Store delivery IDs and ignore duplicates", "Return a 2xx response quickly", "Process longer work asynchronously"],
    "example": {
      "id": "0e56876e-33a8-42f9-a969-acde01234567",
      "event": "katfacil.card.funding_approved",
      "created_at": "2026-09-12T12:00:00Z",
      "data": { "card": { "id": 145, "masked_pan": "**** **** **** 1041", "balance": 26, "currency": "USD" }, "transaction_id": "PGB123456790", "amount": 25, "currency": "USD" }
    }
  },
  "x-katfacil-automatic-termination": {
    "trigger": "Three unique completed authorization-fee events",
    "steps": ["Withdraw the remaining card balance", "Deduct the configured personal or business withdrawal fee", "Credit the net remainder to the main wallet", "Record the transaction and fee breakdown", "Mark the card TERMINATED"],
    "publicApiRequestRequired": false
  }
}
