
Bring data into Shiny on the same port 🚀
Seamlessly integrate POST requests and query parameters into your existing Shiny apps as reactive values. Zero configuration - works with your current UI on the same port.
# Install from CRAN (when available)
install.packages("shinypayload")
# Install development version from GitHub
remotes::install_github("PawanRamaMali/shinypayload")
# For local development
devtools::load_all()library(shiny)
library(shinypayload)
# Your regular UI - no changes needed!
base_ui <- fluidPage(
  titlePanel("🚀 shinypayload Demo"),
  
  fluidRow(
    column(6,
      h4("📊 Live Data"),
      verbatimTextOutput("live_data")
    ),
    column(6,
      h4("🔗 URL Parameters"),
      verbatimTextOutput("url_params")
    )
  ),
  
  hr(),
  h4("📡 POST Endpoint"),
  verbatimTextOutput("endpoint_info")
)
# Wrap your UI to handle POST requests
ui <- payload_ui(
  base_ui,
  path = "/api/data",
  token = Sys.getenv("API_TOKEN", "demo-token")
)
server <- function(input, output, session) {
  # Get URL parameters
  output$url_params <- renderPrint({
    params <- params_get(session)
    if (length(params) > 0) params else "No URL parameters"
  })
  
  # Show endpoint URL
  output$endpoint_info <- renderText({
    url <- payload_endpoint_url(session, "/api/data")
    paste("Send POST requests to:", url, "?token=demo-token")
  })
  
  # React to incoming POST data
  live_data <- payload_last("/api/data", session, intervalMillis = 200)
  
  output$live_data <- renderPrint({
    data <- live_data()
    if (is.null(data)) {
      "Waiting for data... 📡"
    } else {
      list(
        timestamp = data$meta$timestamp,
        payload = data$payload,
        source = data$meta$remote_addr
      )
    }
  })
}
# IMPORTANT: Use uiPattern = ".*" for POST routing
shinyApp(ui, server, uiPattern = ".*")# Send JSON data
curl -X POST "http://localhost:3838/api/data?token=demo-token" \\
  -H "Content-Type: application/json" \\
  -d '{"sensor": "temperature", "value": 23.5, "unit": "celsius"}'
# Send form data  
curl -X POST "http://localhost:3838/api/data?token=demo-token" \\
  -d "name=sensor01&status=active&reading=42"
# Response: {"ok": true}| Function | Purpose | Example | 
|---|---|---|
| payload_ui() | Wrap UI to handle POST requests | payload_ui(my_ui, "/api", "token") | 
| payload_last() | Get reactive with latest POST data | data <- payload_last("/api", session) | 
| params_get() | Extract URL query parameters | params <- params_get(session) | 
| payload_endpoint_url() | Get full endpoint URL | url <- payload_endpoint_url(session, "/api") | 
# Query parameter (recommended)
POST /api/data?token=your-secret-token
# HTTP Headers
POST /api/data
X-Ingress-Token: your-secret-token
# OR
Authorization: your-secret-tokenapplication/json - Parsed with
jsonlite::fromJSON()application/x-www-form-urlencoded - Parsed with
shiny::parseQueryString()Explore our comprehensive examples in inst/examples/:
basic_example.R
- Core functionality demoreal_time_monitor.R
- Live data monitoringform_handler.R
- Form submission processingexisting_app_integration.R
- Add to existing appsEach example includes ready-to-run code and curl commands for testing.
Always use tokens in production
ui <- payload_ui(base_ui, "/api", Sys.getenv("API_SECRET"))Validate and sanitize input data
observeEvent(payload_last("/api", session), {
  data <- payload_last("/api", session)()
  if (!is.null(data)) {
    # Validate required fields
    if (is.null(data$payload$user_id)) return()
    # Sanitize inputs before use
    clean_data <- DBI::dbQuoteString(pool, data$payload$message)
  }
})Use HTTPS in production
Implement rate limiting if needed
Monitor and log API usage
# Handle different data types on different paths
ui <- payload_ui(base_ui, "/sensors", "sensor-token")
server <- function(input, output, session) {
  # Different reactives for different endpoints
  sensor_data <- payload_last("/sensors", session)
  user_data <- payload_last("/users", session)
  
  # Process accordingly...
}# High-frequency updates (100ms)
fast_data <- payload_last("/live", session, intervalMillis = 100)
# Low-frequency updates (5 seconds) 
slow_data <- payload_last("/batch", session, intervalMillis = 5000)We welcome contributions! Please see our Contributing Guidelines for details.
# Clone and install dependencies
git clone https://github.com/PawanRamaMali/shinypayload.git
cd shinypayload
# Install in development mode
devtools::load_all()
# Run tests
devtools::test()
# Check package
devtools::check()This project is licensed under the MIT License - see the LICENSE file for details.
Made with ❤️ for the R and Shiny community