Error UDAPI100500 - "Something went wrong... please contact us"

I have made a script to fetch the historical options data, and it has worked fine… but now it is throwing an error 500 asking to contact support. Could anyone help me with this, what am I missing here ?

I am attaching the code I am using for fetching the options data, please take a look into it, thank you :slight_smile:

import os
from dotenv import load_dotenv
import requests
import json
import pandas as pd
import time

'''

List of some important instrument_keys

    1) NIFTY50  -   NSE_INDEX|Nifty 50
    2) SENSEX30 -   BSE_INDEX|SENSEX

'''

load_dotenv()

access_token = os.getenv("UPSTOX_ACCESS_TOKEN")

url = 'https://api.upstox.com/v2/expired-instruments/expiries'

headers = {
    'Content-Type': 'application/json',
    'Authorization': f'Bearer {access_token}',
    'Accept': 'application/json'
}

instruments = {
    
    'NIFTY50': {'instrument_key': 'NSE_INDEX|Nifty 50'},
    'SENSEX30': {'instrument_key': 'BSE_INDEX|SENSEX'},
    'BANKNIFTY': {'instrument_key': 'NSE_INDEX|Nifty Bank'}

}

for name, info in instruments.items():

    print(f"Fetching expiries for: {name}")

    params = {
        'instrument_key': info['instrument_key']
    }

    response = requests.get(url, params=params, headers=headers)

    if response.status_code == 200:
        dates = sorted(response.json().get('data', []))
        instruments[name]['expiry_dates'] = dates
        # print(json.dumps(response.json(), indent=4))
    else:
        print(f"Error for {name}: {response.status_code} - {response.text}")

print()

# for name, info in instruments.items():
#     print(f"\n{name}:")
#     print(f"Instrument Key: {info['instrument_key']}")
#     for date in info['expiry_dates']:
#         # print(f"\tExpiry Date: {date}")
#         pass


url = 'https://api.upstox.com/v2/expired-instruments/option/contract'

contracts = []

for name, info in instruments.items():

    print(f"Fetching contracts for: {name}")

    instrument_key =  info['instrument_key']

    for expiry in info['expiry_dates']:

        params = {
            'instrument_key' : instrument_key,
            'expiry_date' : expiry
        }

        response = requests.get(url, params=params, headers=headers)

        if response.status_code == 200:
            data = response.json()
            for contract in data.get('data', []):
                contracts.append({
                    'underlying_symbol': contract['underlying_symbol'],
                    'strike_price': contract['strike_price'],
                    'option_type': contract['instrument_type'],
                    'expiry_date': contract['expiry'],
                    'trading_symbol': contract['trading_symbol'],
                    'expired_instrument_key': contract['instrument_key']
                })

                # for x, y in contracts[-1].items():
                #     print(f"{x:25} : {y}")
                # print()
        else:
            print(f"Error: {response.status_code} - {response.text}")

print()

x = 0
limit = 25

base_output_folder = r"data\storage\options\index"

print(f"Total Contracts: {len(contracts)}")
print("Started fetching data...\n")

start_time = time.time()
global_start = time.time()

success = 0
already = 0

rate_limited = 0

for contract in contracts:

    interval = '1minute'
    from_date = '2020-02-24'
    
    instrument_key = contract['expired_instrument_key']
    to_date = contract['expiry_date']

    strike = int(contract['strike_price'])
    underlying = contract['underlying_symbol'].lower()
    symbol = contract['trading_symbol'].replace(" ", "_")
    expiry = contract['expiry_date']

    output_folder = os.path.join(base_output_folder, underlying, expiry)
    os.makedirs(output_folder, exist_ok=True)

    url = f'https://api.upstox.com/v2/expired-instruments/historical-candle/{instrument_key}/{interval}/{to_date}/{from_date}'

    filename = os.path.join(output_folder, f"{symbol}.csv")

    if os.path.exists(filename):
        # x += 1
        # success += 1
        already += 1
        continue

    response = requests.get(url, headers=headers)

    if response.status_code == 200:

        data = response.json()

        df = pd.DataFrame(data.get('data', {}).get('candles', []), columns=['timestamp', 'open', 'high', 'low', 'close', 'volume', 'oi'])

        df = df.iloc[::-1]
        df.to_csv(filename, index=False)
        
        success += 1

        # print(json.dumps(data, indent=4))

    else:

        print(f"\nError: {response.status_code} - {response.text}")

        if (response.status_code == 429):

            # wait 90 seconds before trying again if rate limited

            now = time.time()
            total_time = now - start_time
            
            wait_time = ((31 * 60) - total_time)

            rate_limited += 1
            if rate_limited == 10:
                print("\nRate limit exceeded 10 times, exiting...")
                break

            print(f"Fetched {success} contracts data in {total_time} time...")
            print(f"\nRate limiting, waiting for {wait_time:.2f} seconds...")

            time.sleep(wait_time)
            start_time = time.time()
            continue

        # break

    if (success % 250 == 0):
        print(f"Fetched {success} contracts so far...")
        time.sleep(2)

    if (success % 5000 == 0):
        print("Fetched 5000 contracts, exiting...")
        # time.sleep(60)
        break

    x += 1

end_time = time.time()
total_time = end_time - global_start

print(f"\nTotal time taken {total_time}.")
print(f"Average time per contract: {total_time/success if success > 0 else 0:.2f} seconds.")

print(f"\nAlready existing: {already} contracts.")
print(f"Successfully fetched data for {success} contracts.")

@BHARGAV_53216656 Working fine. I would recommend placing “from_date” on the top and filtering expiries greater than “from_date“. This script is hitting rate limits so fast, so need a fix as well.

Hey, thanks for the reply, it is throwing error for some contracts (I have got know about it now…), and there is an irrevalant break in my code, which has been reason for the script to exit after first api request. Thanks again :slight_smile:

@BHARGAV_53216656 Glad to hear that it’s working for you.

@DSingh Thank you for your support on this.

1 Like

Sir, thank you for your reply.

It’s working fine, but I would like mention that the following contracts are throwing ERROR 500 when requesting for historical data… those contracts were included in the list of contracts that is being returned by the API. Is there any particular reason for this ? or is there anything that I am missing here ?

Expiry - 2025-12-30 Contract - NIFTY 20000 PE 30 DEC 25
Expiry - 2025-12-30 Contract - NIFTY 21000 PE 30 DEC 25
Expiry - 2025-12-30 Contract - NIFTY 22000 PE 30 DEC 25
Expiry - 2025-12-30 Contract - NIFTY 22000 CE 30 DEC 25
Expiry - 2025-12-30 Contract - NIFTY 23000 PE 30 DEC 25
Expiry - 2025-12-30 Contract - NIFTY 23000 CE 30 DEC 25
Expiry - 2025-12-30 Contract - NIFTY 24000 PE 30 DEC 25
Expiry - 2025-12-30 Contract - NIFTY 24000 CE 30 DEC 25
Expiry - 2025-12-30 Contract - NIFTY 25000 PE 30 DEC 25
Expiry - 2025-12-30 Contract - NIFTY 25000 CE 30 DEC 25
Expiry - 2025-12-30 Contract - NIFTY 26000 PE 30 DEC 25
Expiry - 2025-12-30 Contract - NIFTY 26000 CE 30 DEC 25
Expiry - 2025-12-30 Contract - NIFTY 27000 PE 30 DEC 25
Expiry - 2025-12-30 Contract - NIFTY 27000 CE 30 DEC 25
Expiry - 2025-12-30 Contract - NIFTY 28000 PE 30 DEC 25
Expiry - 2025-12-30 Contract - NIFTY 28000 CE 30 DEC 25
Expiry - 2025-12-30 Contract - NIFTY 29000 CE 30 DEC 25
Expiry - 2025-12-30 Contract - NIFTY 30000 CE 30 DEC 25

Please kindly look into it, when you have got some time :slight_smile:

1 Like

@Anand_Sajankar Tested with two URLs from above - URL 1, URL 2. Both returning “http 500: Internal server error“ on “1minute“ interval only and all other intervals are working fine.

@Anand_Sajankar Found the bug. Above instruments are returning data when “to_date“ is set to “2025-09-01“ instead of expiry date of “2025-12-30“. Most probably APIs are mapping instruments incorrectly.

@DSingh @BHARGAV_53216656 It looks like you’re trying to fetch a very large amount of data—from 2020-02-24 to 2025-12-30— using a 1-minute interval. Please try limiting the date range to a maximum of one month for minute-level intervals. This should work correctly.

@Anand_Sajankar Even after removing from_date, it is still returning an error. Eg: https://api.upstox.com/v2/expired-instruments/historical-candle/NSE_FO|38377|30-12-2025/1minute/2025-12-30. Kindly read again my two previous comments.

@DSingh Both from_date and to_date are required parameters for expired historical candle API, refer API document for full details Expired Historical Candle Data | Upstox Developer API

Correct. I missed that point. But still, it seems server issue only as all other instruments are working fine.