{
  "openapi": "3.0.3",
  "info": {
    "title": "PushFTP API",
    "description": "Upload, download, copy, and manage files on SFTP, FTP, and S3 servers through a fixed IP.",
    "version": "1.0.0",
    "contact": {
      "url": "https://pushftp.com/contact"
    }
  },
  "servers": [
    {
      "url": "https://pushftp.com"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key from your PushFTP dashboard. Format: pftp_..."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "Transfer": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "filename": {
            "type": "string"
          },
          "path": {
            "type": "string"
          },
          "size": {
            "type": "integer"
          },
          "durationMs": {
            "type": "integer"
          },
          "connection": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "type": {
                "type": "string"
              }
            }
          }
        }
      },
      "FileInfo": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "path": {
            "type": "string"
          },
          "size": {
            "type": "integer"
          },
          "isDirectory": {
            "type": "boolean"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Connection": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "sftp",
              "ftp",
              "s3"
            ]
          },
          "isActive": {
            "type": "boolean"
          }
        }
      },
      "WatchedFolder": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "connectionId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "path": {
            "type": "string"
          },
          "filePattern": {
            "type": "string",
            "nullable": true
          },
          "scheduleMinutes": {
            "type": "integer"
          },
          "webhookUrl": {
            "type": "string",
            "nullable": true
          },
          "source": {
            "type": "string",
            "description": "How it was created (manual, zapier, etc.)"
          },
          "detectModified": {
            "type": "boolean"
          },
          "isActive": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      }
    }
  },
  "paths": {
    "/api/upload/{connectionId}": {
      "post": {
        "summary": "Upload a file",
        "description": "Upload a file via multipart form data, base64 JSON, or URL fetch.",
        "operationId": "uploadFile",
        "tags": [
          "Files"
        ],
        "parameters": [
          {
            "name": "connectionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "Supports three content types: multipart/form-data (file upload), application/json (base64 or URL), or application/octet-stream (raw binary).",
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  },
                  "path": {
                    "type": "string",
                    "description": "Remote directory"
                  },
                  "filename": {
                    "type": "string",
                    "description": "Override filename"
                  }
                },
                "required": [
                  "file"
                ]
              }
            },
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "content": {
                    "type": "string",
                    "description": "File content as base64"
                  },
                  "url": {
                    "type": "string",
                    "description": "URL to fetch and upload"
                  },
                  "filename": {
                    "type": "string"
                  },
                  "path": {
                    "type": "string",
                    "description": "Remote directory"
                  },
                  "overwrite": {
                    "type": "boolean",
                    "default": true
                  },
                  "filename_template": {
                    "type": "string",
                    "description": "Rename with tokens like {date}, {uuid}"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Upload successful",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "transfer": {
                      "$ref": "#/components/schemas/Transfer"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "File exists and overwrite=false"
          },
          "429": {
            "description": "Transfer limit reached"
          }
        }
      }
    },
    "/api/download/{connectionId}": {
      "get": {
        "summary": "Download a file",
        "description": "Download a file from your server. Returns the raw file by default, or JSON with base64 content if format=json.",
        "operationId": "downloadFile",
        "tags": [
          "Files"
        ],
        "parameters": [
          {
            "name": "connectionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "path",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Remote file path"
          },
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "binary",
                "json"
              ]
            },
            "description": "Response format. Default: binary file download. Use json for base64."
          }
        ],
        "responses": {
          "200": {
            "description": "File content (binary or JSON with base64)"
          }
        }
      }
    },
    "/api/copy": {
      "post": {
        "summary": "Copy a file between connections",
        "description": "Copy a file from one connection to another. Requires Pro plan (multiple connections).",
        "operationId": "copyFile",
        "tags": [
          "Files"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "source_connection_id",
                  "source_path",
                  "dest_connection_id"
                ],
                "properties": {
                  "source_connection_id": {
                    "type": "string"
                  },
                  "source_path": {
                    "type": "string"
                  },
                  "dest_connection_id": {
                    "type": "string"
                  },
                  "dest_path": {
                    "type": "string",
                    "description": "Defaults to source_path if omitted"
                  },
                  "filename_template": {
                    "type": "string"
                  },
                  "overwrite": {
                    "type": "boolean",
                    "default": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Copy successful",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "source": {
                      "type": "object",
                      "properties": {
                        "connectionId": {
                          "type": "string"
                        },
                        "path": {
                          "type": "string"
                        }
                      }
                    },
                    "destination": {
                      "type": "object",
                      "properties": {
                        "connectionId": {
                          "type": "string"
                        },
                        "path": {
                          "type": "string"
                        }
                      }
                    },
                    "fileSize": {
                      "type": "integer"
                    },
                    "durationMs": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/read/{connectionId}": {
      "get": {
        "summary": "Read file contents",
        "description": "Read the text content of a file (max 10 MB). For large files, use /api/download.",
        "operationId": "readFile",
        "tags": [
          "Files"
        ],
        "parameters": [
          {
            "name": "connectionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "path",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "encoding",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "text",
                "base64"
              ],
              "default": "text"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "File content",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "content": {
                      "type": "string"
                    },
                    "encoding": {
                      "type": "string"
                    },
                    "size": {
                      "type": "integer"
                    },
                    "path": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "File too large for read endpoint"
          }
        }
      }
    },
    "/api/write/{connectionId}": {
      "post": {
        "summary": "Write a file",
        "description": "Write text or base64 content to a file on your server.",
        "operationId": "writeFile",
        "tags": [
          "Files"
        ],
        "parameters": [
          {
            "name": "connectionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "path",
                  "content"
                ],
                "properties": {
                  "path": {
                    "type": "string",
                    "description": "Remote file path"
                  },
                  "content": {
                    "type": "string",
                    "description": "File content"
                  },
                  "encoding": {
                    "type": "string",
                    "enum": [
                      "text",
                      "base64"
                    ],
                    "default": "text"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Write successful",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "path": {
                      "type": "string"
                    },
                    "size": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/delete/{connectionId}": {
      "post": {
        "summary": "Delete a file",
        "description": "Delete a file from your server.",
        "operationId": "deleteFile",
        "tags": [
          "Files"
        ],
        "parameters": [
          {
            "name": "connectionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "path"
                ],
                "properties": {
                  "path": {
                    "type": "string",
                    "description": "Remote file path to delete"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Delete successful",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "path": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/move/{connectionId}": {
      "post": {
        "summary": "Move or rename a file",
        "description": "Move a file to a different path or rename it.",
        "operationId": "moveFile",
        "tags": [
          "Files"
        ],
        "parameters": [
          {
            "name": "connectionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "from",
                  "to"
                ],
                "properties": {
                  "from": {
                    "type": "string",
                    "description": "Current file path"
                  },
                  "to": {
                    "type": "string",
                    "description": "New file path"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Move successful",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "from": {
                      "type": "string"
                    },
                    "to": {
                      "type": "string"
                    },
                    "durationMs": {
                      "type": "integer"
                    },
                    "transfer": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/mkdir/{connectionId}": {
      "post": {
        "summary": "Create a folder",
        "description": "Create a directory on your server. Safe to call if it already exists.",
        "operationId": "createFolder",
        "tags": [
          "Server"
        ],
        "parameters": [
          {
            "name": "connectionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "path"
                ],
                "properties": {
                  "path": {
                    "type": "string",
                    "description": "Full path of the folder to create"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Folder created or already exists",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "path": {
                      "type": "string"
                    },
                    "created": {
                      "type": "boolean",
                      "description": "false if folder already existed"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/list/{connectionId}": {
      "get": {
        "summary": "List files in a folder",
        "description": "List all files and directories in a folder.",
        "operationId": "listFiles",
        "tags": [
          "Files"
        ],
        "parameters": [
          {
            "name": "connectionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "path",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Remote folder path. Defaults to connection's default path."
          }
        ],
        "responses": {
          "200": {
            "description": "File listing",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "path": {
                      "type": "string"
                    },
                    "files": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/FileInfo"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/exists/{connectionId}": {
      "get": {
        "summary": "Find a file",
        "description": "Check if a file exists and get its info.",
        "operationId": "findFile",
        "tags": [
          "Files"
        ],
        "parameters": [
          {
            "name": "connectionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "path",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "File info",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "exists": {
                      "type": "boolean"
                    },
                    "file": {
                      "$ref": "#/components/schemas/FileInfo"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/exec/{connectionId}": {
      "post": {
        "summary": "Run SSH command",
        "description": "Execute a shell command on your server via SSH. Requires SFTP connection.",
        "operationId": "runCommand",
        "tags": [
          "Server"
        ],
        "parameters": [
          {
            "name": "connectionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "command"
                ],
                "properties": {
                  "command": {
                    "type": "string",
                    "description": "Shell command to execute"
                  },
                  "timeout": {
                    "type": "integer",
                    "description": "Timeout in milliseconds (max 60000)",
                    "default": 30000
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Command output",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "exitCode": {
                      "type": "integer"
                    },
                    "stdout": {
                      "type": "string"
                    },
                    "stderr": {
                      "type": "string"
                    },
                    "durationMs": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/transfers": {
      "get": {
        "summary": "List transfers",
        "description": "List transfer history. Supports filtering by connection, status, type, and date.",
        "operationId": "listTransfers",
        "tags": [
          "Account"
        ],
        "parameters": [
          {
            "name": "connection_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "success",
                "failed",
                "pending"
              ]
            }
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "upload",
                "download",
                "poll",
                "email",
                "copy",
                "append"
              ]
            }
          },
          {
            "name": "since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Only transfers after this date"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20,
              "maximum": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Transfer list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "transfers": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "connectionId": {
                            "type": "string"
                          },
                          "type": {
                            "type": "string"
                          },
                          "direction": {
                            "type": "string"
                          },
                          "filename": {
                            "type": "string"
                          },
                          "path": {
                            "type": "string"
                          },
                          "fileSize": {
                            "type": "integer"
                          },
                          "status": {
                            "type": "string"
                          },
                          "errorMessage": {
                            "type": "string",
                            "nullable": true
                          },
                          "durationMs": {
                            "type": "integer"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "total": {
                      "type": "integer"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/connections": {
      "get": {
        "summary": "List connections",
        "description": "List all your connections.",
        "operationId": "listConnections",
        "tags": [
          "Account"
        ],
        "responses": {
          "200": {
            "description": "Connection list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "connections": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Connection"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/me": {
      "get": {
        "summary": "Verify API key",
        "description": "Verify your API key and get account info.",
        "operationId": "verifyApiKey",
        "tags": [
          "Account"
        ],
        "responses": {
          "200": {
            "description": "Account info",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "email": {
                      "type": "string"
                    },
                    "plan": {
                      "type": "string"
                    },
                    "connections": {
                      "type": "integer"
                    },
                    "transfers": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/append/{connectionId}": {
      "post": {
        "summary": "Append to a file",
        "description": "Append text or base64 content to an existing file. Not supported on S3.",
        "operationId": "appendFile",
        "tags": [
          "Files"
        ],
        "parameters": [
          {
            "name": "connectionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "path",
                  "content"
                ],
                "properties": {
                  "path": {
                    "type": "string",
                    "description": "Remote file path to append to"
                  },
                  "content": {
                    "type": "string",
                    "description": "Content to append"
                  },
                  "encoding": {
                    "type": "string",
                    "enum": [
                      "text",
                      "base64"
                    ],
                    "default": "text"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Append successful",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "transfer": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "filename": {
                          "type": "string"
                        },
                        "path": {
                          "type": "string"
                        },
                        "appendedBytes": {
                          "type": "integer"
                        },
                        "durationMs": {
                          "type": "integer"
                        },
                        "connection": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "name": {
                              "type": "string"
                            },
                            "type": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Not supported on S3 connections"
          }
        }
      }
    },
    "/api/watched-folders": {
      "get": {
        "summary": "List watched folders",
        "description": "List all watched folders for your account.",
        "operationId": "listWatchedFolders",
        "tags": [
          "Watched Folders"
        ],
        "responses": {
          "200": {
            "description": "Watched folder list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "watchedFolders": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WatchedFolder"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a watched folder",
        "description": "Watch a folder on your server for new or modified files. PushFTP checks the folder at the configured interval and fires a webhook when changes are detected.",
        "operationId": "createWatchedFolder",
        "tags": [
          "Watched Folders"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "connectionId",
                  "path"
                ],
                "properties": {
                  "connectionId": {
                    "type": "string",
                    "description": "Connection to watch"
                  },
                  "path": {
                    "type": "string",
                    "description": "Folder path to watch"
                  },
                  "webhookUrl": {
                    "type": "string",
                    "description": "URL to POST when new files are detected"
                  },
                  "filePattern": {
                    "type": "string",
                    "description": "Glob pattern to filter files (e.g. *.csv)",
                    "nullable": true
                  },
                  "scheduleMinutes": {
                    "type": "integer",
                    "description": "Check interval in minutes (1–1440)",
                    "default": 5
                  },
                  "name": {
                    "type": "string",
                    "description": "Display name for the watched folder"
                  },
                  "detectModified": {
                    "type": "boolean",
                    "description": "Also trigger on modified files (size or date changed)",
                    "default": false
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Watched folder created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WatchedFolder"
                }
              }
            }
          }
        }
      }
    },
    "/api/watched-folders/{id}": {
      "delete": {
        "summary": "Delete a watched folder",
        "description": "Stop watching a folder and remove it.",
        "operationId": "deleteWatchedFolder",
        "tags": [
          "Watched Folders"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Watched folder ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Watched folder not found"
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Files",
      "description": "Upload, download, copy, move, delete, read, list, and find files"
    },
    {
      "name": "Server",
      "description": "Create folders and run SSH commands"
    },
    {
      "name": "Account",
      "description": "Connections, transfers, and API key verification"
    },
    {
      "name": "Watched Folders",
      "description": "Monitor folders for new and modified files"
    }
  ]
}