Trying to get live stock data via python

I’m trying to create a web app in python using Anvil and access Alpaca API for live stock data of AAPL

server code



@anvil.server.callable
def get_live_apple_prices():
  url = "https://data.alpaca.markets/v2/stocks/bars"

  now = datetime.now(timezone.utc).replace(microsecond=0)
  start = now - timedelta(minutes=15)

  # Format ISO timestamps with 'Z' instead of '+00:00'
  start_str = start.isoformat().replace("+00:00", "Z")
  end_str = now.isoformat().replace("+00:00", "Z")

  full_url = (
    f"{url}?symbols=AAPL"
    f"&start={start_str}"
    f"&end={end_str}"
    f"&timeframe=1Min"
  )

  print("Requesting:", full_url)

  r = requests.get(full_url, headers=headers)
  r.raise_for_status()

  bars = r.json().get("bars", {}).get("AAPL", [])

  return {
    "times": [b["t"] for b in bars],
    "prices": [b["c"] for b in bars]
  }


client code 

self.init_components(**properties)
    self.update_chart()

  def update_chart(self):
      data = anvil.server.call('get_live_apple_prices')
      
      x = [datetime.fromisoformat(t.rstrip("Z")) - timedelta(hours=4) for t in data["times"]]  # UTC → EST
      y = data["prices"]

      fig = go.Figure(
        data=[go.Scatter(x=x, y=y, mode="lines+markers")],
        layout=dict(
          title="AAPL – Live (Last 15 Minutes)",
          xaxis_title="Time (EST)",
          yaxis_title="Price (USD)"
        )
      )

      self.plot_1.figure = fig
      if hasattr(self, 'status_label'):
        self.status_label.text = "Live data updated"

  def timer_1_tick(self, **event_args):
    self.update_chart()

When I do this it returns a 403 HTTP error and my API KEY and Secret Key are correct, so im guessing its the url but I’m not sure how to go about this

Don’t re-invent the wheel. Use the supported python package:

pip install alpaca-py

View the example of fetching market data:

@Raymond The issue may be your Market Data subscription. Unless you have an Algo Trader Plus subscription you will not be able to query the most recent 15 minutes of data. The free Basic subscription only allows for 15 minute delayed data.

One ‘trick’ is to omit the end parameter. The APIs will default to the most current time your subscription allows. Additionally, always include a feed parameter. You generally always want feed=sip for full market data.

Though it may be as simple as you didn’t define headers? I don’t see it in the code. It should be something like this

headers = {
    "accept": "application/json",
    "APCA-API-KEY-ID": your api key,
    "APCA-API-SECRET-KEY": your secret
}