{
  "openapi": "3.1.0",
  "info": {
    "title": "Fapshi Payment API",
    "description": "API for generating payment links, direct payments, transaction monitoring, payouts, and more.",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://sandbox.fapshi.com"
    }
  ],
  "security": [
    {
      "apiAuth": [],
      "apiKey": []
    }
  ],
  "paths": {
    "/initiate-pay": {
      "post": {
        "summary": "Generate a Payment Link",
        "description": "Create a payment link where users complete payment on a Fapshi-hosted checkout page.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "amount": {
                    "type": "integer",
                    "minimum": 100,
                    "description": "Amount to be paid (minimum 100 XAF)."
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Optional user email to skip during payment."
                  },
                  "redirectUrl": {
                    "type": "string",
                    "format": "uri",
                    "description": "URL to redirect after payment."
                  },
                  "userId": {
                    "type": "string",
                    "pattern": "^[a-zA-Z0-9\\-_]{1,100}$",
                    "description": "Internal user ID (1-100 chars; a-z, A-Z, 0-9, -, _)."
                  },
                  "externalId": {
                    "type": "string",
                    "pattern": "^[a-zA-Z0-9\\-_]{1,100}$",
                    "description": "Transaction/order ID for reconciliation (1-100 chars; a-z, A-Z, 0-9, -, _)."
                  },
                  "message": {
                    "type": "string",
                    "description": "Reason for payment."
                  }
                },
                "required": ["amount"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Payment link generated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "description": "Success message"
                    },
                    "link": {
                      "type": "string",
                      "format": "uri",
                      "description": "URL to redirect the user to complete payment."
                    },
                    "transId": {
                      "type": "string",
                      "description": "Transaction ID for payment."
                    },
                    "dateInitiated": {
                      "type": "string",
                      "format": "date",
                      "description": "Date when the payment was initiated."
                    }
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "Client error, e.g., invalid request or parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/direct-pay": {
      "post": {
        "summary": "Initiate a Direct Payment Request",
        "description": "Send a payment request directly to a user's mobile device for confirmation.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "amount": {
                    "type": "integer",
                    "minimum": 100,
                    "description": "Amount to be paid (minimum 100 XAF)."
                  },
                  "phone": {
                    "type": "string",
                    "description": "Phone number where payment request is sent."
                  },
                  "medium": {
                    "type": "string",
                    "enum": ["mobile money", "orange money"],
                    "description": "Payment medium (optional)."
                  },
                  "name": {
                    "type": "string",
                    "description": "Name of the payer (optional)."
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Email of the payer for receipts (optional)."
                  },
                  "userId": {
                    "type": "string",
                    "pattern": "^[a-zA-Z0-9\\-_]{1,100}$",
                    "description": "Internal user ID (optional)."
                  },
                  "externalId": {
                    "type": "string",
                    "pattern": "^[a-zA-Z0-9\\-_]{1,100}$",
                    "description": "Transaction/order ID for reconciliation (optional)."
                  },
                  "message": {
                    "type": "string",
                    "description": "Reason for payment (optional)."
                  }
                },
                "required": ["amount", "phone"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Accepted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "description": "Success message"
                    },
                    "transId": {
                      "type": "string",
                      "description": "Transaction ID for the payment."
                    },
                    "dateInitiated": {
                      "type": "string",
                      "format": "date",
                      "description": "Date when the payment was initiated."
                    }
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "Client error, e.g., invalid credentials or parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/payment-status/{transId}": {
      "get": {
        "summary": "Get Payment Transaction Status",
        "description": "Retrieve the status of a payment transaction by its transaction ID.",
        "parameters": [
          {
            "name": "transId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Transaction ID of the payment."
          }
        ],
        "responses": {
          "200": {
            "description": "Payment status retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Transaction"
                }
              }
            }
          },
          "4XX": {
            "description": "Invalid transaction ID or error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/expire-pay": {
      "post": {
        "summary": "Expire a Payment Transaction",
        "description": "Invalidate a payment link to prevent further payments.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "transId": {
                    "type": "string",
                    "description": "Transaction ID to expire."
                  }
                },
                "required": ["transId"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Payment link expired successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Transaction"
                }
              }
            }
          },
          "400": {
            "description": "Link already expired or invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/transaction/{userId}": {
      "get": {
        "summary": "Get Transactions by User ID",
        "description": "Retrieve all transactions associated with a specific user ID.",
        "parameters": [
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-zA-Z0-9\\-_]{1,100}$"
            },
            "description": "User ID to retrieve transactions for."
          }
        ],
        "responses": {
          "200": {
            "description": "List of transactions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Transaction"
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "Invalid user ID or error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/search": {
      "get": {
        "summary": "Search Transactions",
        "description": "Search transactions by various filters.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["created", "successful", "failed", "expired"]
            },
            "description": "Filter by transaction status."
          },
          {
            "name": "medium",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["mobile money", "orange money"]
            },
            "description": "Filter by payment medium."
          },
          {
            "name": "start",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Start date (YYYY-MM-DD)."
          },
          {
            "name": "end",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "End date (YYYY-MM-DD)."
          },
          {
            "name": "amt",
            "in": "query",
            "schema": {
              "type": "integer"
            },
            "description": "Exact amount to filter."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 10
            },
            "description": "Maximum number of results."
          },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["asc", "desc"],
              "default": "desc"
            },
            "description": "Sort order."
          }
        ],
        "responses": {
          "200": {
            "description": "Filtered list of transactions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Transaction"
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "Invalid query parameters or error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/balance": {
      "get": {
        "summary": "Get Service Balance",
        "description": "Returns the current balance of the service account.",
        "responses": {
          "200": {
            "description": "Current balance returned",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "service": {
                      "type": "string",
                      "description": "The service whose balance you've queried."
                    },
                    "balance": {
                      "type": "integer",
                      "description": "Current balance amount."
                    },
                    "currency": {
                      "type": "string",
                      "description": "Currency."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/payout": {
      "post": {
        "summary": "Make a Payout",
        "description": "Send money to a user's mobile money, orange money or fapshi account via a payout-enabled service. When `medium` is not specified, `amount` and `phone` are required. When `medium` is set to `\"fapshi\"`, `amount` and `email` are required.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "amount": {
                    "type": "integer",
                    "minimum": 100,
                    "description": "Amount to send (minimum 100 XAF)."
                  },
                  "phone": {
                    "type": "string",
                    "description": "Recipient phone number. Required when `medium` is not specified or not `\"fapshi\"`. Not required when `medium` is `\"fapshi\"`."
                  },
                  "medium": {
                    "type": "string",
                    "enum": ["mobile money", "orange money", "fapshi"],
                    "description": "Payment medium (optional). Auto-detected if omitted (requires `phone`). When set to `\"fapshi\"`, `email` is required instead of `phone`."
                  },
                  "name": {
                    "type": "string",
                    "description": "Recipient name (optional)."
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Recipient email. Required when `medium` is `\"fapshi\"`. Optional for payout receipt when `medium` is not `\"fapshi\"`."
                  },
                  "userId": {
                    "type": "string",
                    "pattern": "^[a-zA-Z0-9\\-_]{1,100}$",
                    "description": "User ID for payout tracking (optional)."
                  },
                  "externalId": {
                    "type": "string",
                    "pattern": "^[a-zA-Z0-9\\-_]{1,100}$",
                    "description": "Transaction/order ID for reconciliation (optional)."
                  },
                  "message": {
                    "type": "string",
                    "description": "Reason for payout (optional)."
                  }
                },
                "required": ["amount"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Accepted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "description": "Success message"
                    },
                    "transId": {
                      "type": "string",
                      "description": "Transaction ID for the payment."
                    },
                    "dateInitiated": {
                      "type": "string",
                      "format": "date",
                      "description": "Date when the payment was initiated."
                    }
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "Invalid request or insufficient permissions",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "/webhook/payment-status": {
      "post": {
        "description": "Notifies your application when the status of a payment changes (SUCCESSFUL, FAILED, EXPIRED).",
        "security": [],
        "responses": {
          "200": {
            "description": "Acknowledgement of webhook receipt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Transaction"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "apiuser"
      },
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "apikey"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "description": "Error message."
          }
        }
      },
      "Transaction": {
        "type": "object",
        "properties": {
          "transId": {
            "type": "string",
            "description": "Transaction ID of the payment."
          },
          "status": {
            "type": "string",
            "enum": ["CREATED", "PENDING", "SUCCESSFUL", "FAILED", "EXPIRED"],
            "description": "Transaction status"
          },
          "medium": {
            "type": "string",
            "enum": ["mobile money", "orange money", "fapshi"],
            "description": "Payment method"
          },
          "serviceName": {
            "type": "string",
            "description": "Name of the service in use"
          },
          "transType": {
            "type": "string",
            "enum": ["Collection", "Payout"],
            "description": "Type of transaction"
          },
          "amount": {
            "type": "integer",
            "description": "Transaction amount"
          },
          "revenue": {
            "type": "integer",
            "description": "Amount received when Fapshi fees have been deducted"
          },
          "payerName": {
            "type": "string",
            "description": "Client name"
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Client email"
          },
          "redirectUrl": {
            "type": "string",
            "format": "uri",
            "description": "URL to redirect after payment"
          },
          "externalId": {
            "type": "string",
            "description": "The transaction ID on your application"
          },
          "userId": {
            "type": "string",
            "description": "ID of the client on your application"
          },
          "webhook": {
            "type": "string",
            "format": "uri",
            "description": "The webhook you defined for your service"
          },
          "reason": {
            "type": "string",
            "description": "Typically appears when a payout via fapshi fails"
          },
          "financialTransId": {
            "type": "string",
            "description": "Transaction ID with the payment operator"
          },
          "dateInitiated": {
            "type": "string",
            "format": "date",
            "description": "Date when the payment was initiated"
          },
          "dateConfirmed": {
            "type": "string",
            "format": "date",
            "description": "Date when the payment was made"
          }
        }
      }
    }
  }
}
